scipy 1.15.3__cp312-cp312-macosx_12_0_arm64.whl → 1.16.0rc2__cp312-cp312-macosx_12_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- scipy/.dylibs/libscipy_openblas.dylib +0 -0
- scipy/__config__.py +8 -8
- scipy/__init__.py +3 -6
- scipy/_cyutility.cpython-312-darwin.so +0 -0
- scipy/_lib/_array_api.py +486 -161
- scipy/_lib/_array_api_compat_vendor.py +9 -0
- scipy/_lib/_bunch.py +4 -0
- scipy/_lib/_ccallback_c.cpython-312-darwin.so +0 -0
- scipy/_lib/_docscrape.py +1 -1
- scipy/_lib/_elementwise_iterative_method.py +15 -26
- scipy/_lib/_sparse.py +41 -0
- scipy/_lib/_test_deprecation_call.cpython-312-darwin.so +0 -0
- scipy/_lib/_test_deprecation_def.cpython-312-darwin.so +0 -0
- scipy/_lib/_testutils.py +6 -2
- scipy/_lib/_util.py +222 -125
- scipy/_lib/array_api_compat/__init__.py +4 -4
- scipy/_lib/array_api_compat/_internal.py +19 -6
- scipy/_lib/array_api_compat/common/__init__.py +1 -1
- scipy/_lib/array_api_compat/common/_aliases.py +365 -193
- scipy/_lib/array_api_compat/common/_fft.py +94 -64
- scipy/_lib/array_api_compat/common/_helpers.py +413 -180
- scipy/_lib/array_api_compat/common/_linalg.py +116 -40
- scipy/_lib/array_api_compat/common/_typing.py +179 -10
- scipy/_lib/array_api_compat/cupy/__init__.py +1 -4
- scipy/_lib/array_api_compat/cupy/_aliases.py +61 -41
- scipy/_lib/array_api_compat/cupy/_info.py +16 -6
- scipy/_lib/array_api_compat/cupy/_typing.py +24 -39
- scipy/_lib/array_api_compat/dask/array/__init__.py +6 -3
- scipy/_lib/array_api_compat/dask/array/_aliases.py +267 -108
- scipy/_lib/array_api_compat/dask/array/_info.py +105 -34
- scipy/_lib/array_api_compat/dask/array/fft.py +5 -8
- scipy/_lib/array_api_compat/dask/array/linalg.py +21 -22
- scipy/_lib/array_api_compat/numpy/__init__.py +13 -15
- scipy/_lib/array_api_compat/numpy/_aliases.py +98 -49
- scipy/_lib/array_api_compat/numpy/_info.py +36 -16
- scipy/_lib/array_api_compat/numpy/_typing.py +27 -43
- scipy/_lib/array_api_compat/numpy/fft.py +11 -5
- scipy/_lib/array_api_compat/numpy/linalg.py +75 -22
- scipy/_lib/array_api_compat/torch/__init__.py +3 -5
- scipy/_lib/array_api_compat/torch/_aliases.py +262 -159
- scipy/_lib/array_api_compat/torch/_info.py +27 -16
- scipy/_lib/array_api_compat/torch/_typing.py +3 -0
- scipy/_lib/array_api_compat/torch/fft.py +17 -18
- scipy/_lib/array_api_compat/torch/linalg.py +16 -16
- scipy/_lib/array_api_extra/__init__.py +26 -3
- scipy/_lib/array_api_extra/_delegation.py +171 -0
- scipy/_lib/array_api_extra/_lib/__init__.py +1 -0
- scipy/_lib/array_api_extra/_lib/_at.py +463 -0
- scipy/_lib/array_api_extra/_lib/_backends.py +46 -0
- scipy/_lib/array_api_extra/_lib/_funcs.py +937 -0
- scipy/_lib/array_api_extra/_lib/_lazy.py +357 -0
- scipy/_lib/array_api_extra/_lib/_testing.py +278 -0
- scipy/_lib/array_api_extra/_lib/_utils/__init__.py +1 -0
- scipy/_lib/array_api_extra/_lib/_utils/_compat.py +74 -0
- scipy/_lib/array_api_extra/_lib/_utils/_compat.pyi +45 -0
- scipy/_lib/array_api_extra/_lib/_utils/_helpers.py +559 -0
- scipy/_lib/array_api_extra/_lib/_utils/_typing.py +10 -0
- scipy/_lib/array_api_extra/_lib/_utils/_typing.pyi +105 -0
- scipy/_lib/array_api_extra/testing.py +359 -0
- scipy/_lib/decorator.py +2 -2
- scipy/_lib/doccer.py +1 -7
- scipy/_lib/messagestream.cpython-312-darwin.so +0 -0
- scipy/_lib/pyprima/__init__.py +212 -0
- scipy/_lib/pyprima/cobyla/__init__.py +0 -0
- scipy/_lib/pyprima/cobyla/cobyla.py +559 -0
- scipy/_lib/pyprima/cobyla/cobylb.py +714 -0
- scipy/_lib/pyprima/cobyla/geometry.py +226 -0
- scipy/_lib/pyprima/cobyla/initialize.py +215 -0
- scipy/_lib/pyprima/cobyla/trustregion.py +492 -0
- scipy/_lib/pyprima/cobyla/update.py +289 -0
- scipy/_lib/pyprima/common/__init__.py +0 -0
- scipy/_lib/pyprima/common/_bounds.py +34 -0
- scipy/_lib/pyprima/common/_linear_constraints.py +46 -0
- scipy/_lib/pyprima/common/_nonlinear_constraints.py +54 -0
- scipy/_lib/pyprima/common/_project.py +173 -0
- scipy/_lib/pyprima/common/checkbreak.py +93 -0
- scipy/_lib/pyprima/common/consts.py +47 -0
- scipy/_lib/pyprima/common/evaluate.py +99 -0
- scipy/_lib/pyprima/common/history.py +38 -0
- scipy/_lib/pyprima/common/infos.py +30 -0
- scipy/_lib/pyprima/common/linalg.py +435 -0
- scipy/_lib/pyprima/common/message.py +290 -0
- scipy/_lib/pyprima/common/powalg.py +131 -0
- scipy/_lib/pyprima/common/preproc.py +277 -0
- scipy/_lib/pyprima/common/present.py +5 -0
- scipy/_lib/pyprima/common/ratio.py +54 -0
- scipy/_lib/pyprima/common/redrho.py +47 -0
- scipy/_lib/pyprima/common/selectx.py +296 -0
- scipy/_lib/tests/test__util.py +105 -121
- scipy/_lib/tests/test_array_api.py +166 -35
- scipy/_lib/tests/test_bunch.py +7 -0
- scipy/_lib/tests/test_ccallback.py +2 -10
- scipy/_lib/tests/test_public_api.py +13 -0
- scipy/cluster/_hierarchy.cpython-312-darwin.so +0 -0
- scipy/cluster/_optimal_leaf_ordering.cpython-312-darwin.so +0 -0
- scipy/cluster/_vq.cpython-312-darwin.so +0 -0
- scipy/cluster/hierarchy.py +393 -223
- scipy/cluster/tests/test_hierarchy.py +273 -335
- scipy/cluster/tests/test_vq.py +45 -61
- scipy/cluster/vq.py +39 -35
- scipy/conftest.py +263 -157
- scipy/constants/_constants.py +4 -1
- scipy/constants/tests/test_codata.py +2 -2
- scipy/constants/tests/test_constants.py +11 -18
- scipy/datasets/_download_all.py +15 -1
- scipy/datasets/_fetchers.py +7 -1
- scipy/datasets/_utils.py +1 -1
- scipy/differentiate/_differentiate.py +25 -25
- scipy/differentiate/tests/test_differentiate.py +24 -25
- scipy/fft/_basic.py +20 -0
- scipy/fft/_helper.py +3 -34
- scipy/fft/_pocketfft/helper.py +29 -1
- scipy/fft/_pocketfft/tests/test_basic.py +2 -4
- scipy/fft/_pocketfft/tests/test_real_transforms.py +4 -4
- scipy/fft/_realtransforms.py +13 -0
- scipy/fft/tests/test_basic.py +27 -25
- scipy/fft/tests/test_fftlog.py +16 -7
- scipy/fft/tests/test_helper.py +18 -34
- scipy/fft/tests/test_real_transforms.py +8 -10
- scipy/fftpack/convolve.cpython-312-darwin.so +0 -0
- scipy/fftpack/tests/test_basic.py +2 -4
- scipy/fftpack/tests/test_real_transforms.py +8 -9
- scipy/integrate/_bvp.py +9 -3
- scipy/integrate/_cubature.py +3 -2
- scipy/integrate/_dop.cpython-312-darwin.so +0 -0
- scipy/integrate/_lsoda.cpython-312-darwin.so +0 -0
- scipy/integrate/_ode.py +9 -2
- scipy/integrate/_odepack.cpython-312-darwin.so +0 -0
- scipy/integrate/_quad_vec.py +21 -29
- scipy/integrate/_quadpack.cpython-312-darwin.so +0 -0
- scipy/integrate/_quadpack_py.py +11 -7
- scipy/integrate/_quadrature.py +3 -3
- scipy/integrate/_rules/_base.py +2 -2
- scipy/integrate/_tanhsinh.py +48 -47
- scipy/integrate/_test_odeint_banded.cpython-312-darwin.so +0 -0
- scipy/integrate/_vode.cpython-312-darwin.so +0 -0
- scipy/integrate/tests/test__quad_vec.py +0 -6
- scipy/integrate/tests/test_banded_ode_solvers.py +85 -0
- scipy/integrate/tests/test_cubature.py +21 -35
- scipy/integrate/tests/test_quadrature.py +6 -8
- scipy/integrate/tests/test_tanhsinh.py +56 -48
- scipy/interpolate/__init__.py +70 -58
- scipy/interpolate/_bary_rational.py +22 -22
- scipy/interpolate/_bsplines.py +119 -66
- scipy/interpolate/_cubic.py +65 -50
- scipy/interpolate/_dfitpack.cpython-312-darwin.so +0 -0
- scipy/interpolate/_dierckx.cpython-312-darwin.so +0 -0
- scipy/interpolate/_fitpack.cpython-312-darwin.so +0 -0
- scipy/interpolate/_fitpack2.py +9 -6
- scipy/interpolate/_fitpack_impl.py +32 -26
- scipy/interpolate/_fitpack_repro.py +23 -19
- scipy/interpolate/_interpnd.cpython-312-darwin.so +0 -0
- scipy/interpolate/_interpolate.py +30 -12
- scipy/interpolate/_ndbspline.py +13 -18
- scipy/interpolate/_ndgriddata.py +5 -8
- scipy/interpolate/_polyint.py +95 -31
- scipy/interpolate/_ppoly.cpython-312-darwin.so +0 -0
- scipy/interpolate/_rbf.py +2 -2
- scipy/interpolate/_rbfinterp.py +1 -1
- scipy/interpolate/_rbfinterp_pythran.cpython-312-darwin.so +0 -0
- scipy/interpolate/_rgi.py +31 -26
- scipy/interpolate/_rgi_cython.cpython-312-darwin.so +0 -0
- scipy/interpolate/dfitpack.py +0 -20
- scipy/interpolate/interpnd.py +1 -2
- scipy/interpolate/tests/test_bary_rational.py +2 -2
- scipy/interpolate/tests/test_bsplines.py +97 -1
- scipy/interpolate/tests/test_fitpack2.py +39 -1
- scipy/interpolate/tests/test_interpnd.py +32 -20
- scipy/interpolate/tests/test_interpolate.py +48 -4
- scipy/interpolate/tests/test_rgi.py +2 -1
- scipy/io/_fast_matrix_market/__init__.py +2 -0
- scipy/io/_harwell_boeing/_fortran_format_parser.py +19 -16
- scipy/io/_harwell_boeing/hb.py +7 -11
- scipy/io/_idl.py +5 -7
- scipy/io/_netcdf.py +15 -5
- scipy/io/_test_fortran.cpython-312-darwin.so +0 -0
- scipy/io/arff/tests/test_arffread.py +3 -3
- scipy/io/matlab/__init__.py +5 -3
- scipy/io/matlab/_mio.py +4 -1
- scipy/io/matlab/_mio5.py +19 -13
- scipy/io/matlab/_mio5_utils.cpython-312-darwin.so +0 -0
- scipy/io/matlab/_mio_utils.cpython-312-darwin.so +0 -0
- scipy/io/matlab/_miobase.py +4 -1
- scipy/io/matlab/_streams.cpython-312-darwin.so +0 -0
- scipy/io/matlab/tests/test_mio.py +46 -18
- scipy/io/matlab/tests/test_mio_funcs.py +1 -1
- scipy/io/tests/test_mmio.py +7 -1
- scipy/io/tests/test_wavfile.py +41 -0
- scipy/io/wavfile.py +57 -10
- scipy/linalg/_basic.py +113 -86
- scipy/linalg/_cythonized_array_utils.cpython-312-darwin.so +0 -0
- scipy/linalg/_decomp.py +22 -9
- scipy/linalg/_decomp_cholesky.py +28 -13
- scipy/linalg/_decomp_cossin.py +45 -30
- scipy/linalg/_decomp_interpolative.cpython-312-darwin.so +0 -0
- scipy/linalg/_decomp_ldl.py +4 -1
- scipy/linalg/_decomp_lu.py +18 -6
- scipy/linalg/_decomp_lu_cython.cpython-312-darwin.so +0 -0
- scipy/linalg/_decomp_polar.py +2 -0
- scipy/linalg/_decomp_qr.py +6 -2
- scipy/linalg/_decomp_qz.py +3 -0
- scipy/linalg/_decomp_schur.py +3 -1
- scipy/linalg/_decomp_svd.py +13 -2
- scipy/linalg/_decomp_update.cpython-312-darwin.so +0 -0
- scipy/linalg/_expm_frechet.py +4 -0
- scipy/linalg/_fblas.cpython-312-darwin.so +0 -0
- scipy/linalg/_flapack.cpython-312-darwin.so +0 -0
- scipy/linalg/_linalg_pythran.cpython-312-darwin.so +0 -0
- scipy/linalg/_matfuncs.py +187 -4
- scipy/linalg/_matfuncs_expm.cpython-312-darwin.so +0 -0
- scipy/linalg/_matfuncs_schur_sqrtm.cpython-312-darwin.so +0 -0
- scipy/linalg/_matfuncs_sqrtm.py +1 -99
- scipy/linalg/_matfuncs_sqrtm_triu.cpython-312-darwin.so +0 -0
- scipy/linalg/_procrustes.py +2 -0
- scipy/linalg/_sketches.py +17 -6
- scipy/linalg/_solve_toeplitz.cpython-312-darwin.so +0 -0
- scipy/linalg/_solvers.py +7 -2
- scipy/linalg/_special_matrices.py +26 -36
- scipy/linalg/cython_blas.cpython-312-darwin.so +0 -0
- scipy/linalg/cython_lapack.cpython-312-darwin.so +0 -0
- scipy/linalg/lapack.py +22 -2
- scipy/linalg/tests/_cython_examples/meson.build +7 -0
- scipy/linalg/tests/test_basic.py +31 -16
- scipy/linalg/tests/test_batch.py +588 -0
- scipy/linalg/tests/test_cythonized_array_utils.py +0 -2
- scipy/linalg/tests/test_decomp.py +40 -3
- scipy/linalg/tests/test_decomp_cossin.py +14 -0
- scipy/linalg/tests/test_decomp_ldl.py +1 -1
- scipy/linalg/tests/test_lapack.py +115 -7
- scipy/linalg/tests/test_matfuncs.py +157 -102
- scipy/linalg/tests/test_procrustes.py +0 -7
- scipy/linalg/tests/test_solve_toeplitz.py +1 -1
- scipy/linalg/tests/test_special_matrices.py +1 -5
- scipy/ndimage/__init__.py +1 -0
- scipy/ndimage/_cytest.cpython-312-darwin.so +0 -0
- scipy/ndimage/_delegators.py +8 -2
- scipy/ndimage/_filters.py +453 -5
- scipy/ndimage/_interpolation.py +36 -6
- scipy/ndimage/_measurements.py +4 -2
- scipy/ndimage/_morphology.py +5 -0
- scipy/ndimage/_nd_image.cpython-312-darwin.so +0 -0
- scipy/ndimage/_ni_docstrings.py +5 -1
- scipy/ndimage/_ni_label.cpython-312-darwin.so +0 -0
- scipy/ndimage/_ni_support.py +1 -5
- scipy/ndimage/_rank_filter_1d.cpython-312-darwin.so +0 -0
- scipy/ndimage/_support_alternative_backends.py +18 -6
- scipy/ndimage/tests/test_filters.py +370 -259
- scipy/ndimage/tests/test_fourier.py +7 -9
- scipy/ndimage/tests/test_interpolation.py +68 -61
- scipy/ndimage/tests/test_measurements.py +18 -35
- scipy/ndimage/tests/test_morphology.py +143 -131
- scipy/ndimage/tests/test_splines.py +1 -3
- scipy/odr/__odrpack.cpython-312-darwin.so +0 -0
- scipy/optimize/_basinhopping.py +13 -7
- scipy/optimize/_bglu_dense.cpython-312-darwin.so +0 -0
- scipy/optimize/_bracket.py +17 -24
- scipy/optimize/_chandrupatla.py +9 -10
- scipy/optimize/_cobyla_py.py +104 -123
- scipy/optimize/_constraints.py +14 -10
- scipy/optimize/_differentiable_functions.py +371 -230
- scipy/optimize/_differentialevolution.py +4 -3
- scipy/optimize/_direct.cpython-312-darwin.so +0 -0
- scipy/optimize/_dual_annealing.py +1 -1
- scipy/optimize/_elementwise.py +1 -4
- scipy/optimize/_group_columns.cpython-312-darwin.so +0 -0
- scipy/optimize/_lbfgsb.cpython-312-darwin.so +0 -0
- scipy/optimize/_lbfgsb_py.py +57 -16
- scipy/optimize/_linprog_doc.py +2 -2
- scipy/optimize/_linprog_highs.py +2 -2
- scipy/optimize/_linprog_ip.py +25 -10
- scipy/optimize/_linprog_util.py +14 -16
- scipy/optimize/_lsap.cpython-312-darwin.so +0 -0
- scipy/optimize/_lsq/common.py +3 -3
- scipy/optimize/_lsq/dogbox.py +16 -2
- scipy/optimize/_lsq/givens_elimination.cpython-312-darwin.so +0 -0
- scipy/optimize/_lsq/least_squares.py +198 -126
- scipy/optimize/_lsq/lsq_linear.py +6 -6
- scipy/optimize/_lsq/trf.py +35 -8
- scipy/optimize/_milp.py +3 -1
- scipy/optimize/_minimize.py +105 -36
- scipy/optimize/_minpack.cpython-312-darwin.so +0 -0
- scipy/optimize/_minpack_py.py +21 -14
- scipy/optimize/_moduleTNC.cpython-312-darwin.so +0 -0
- scipy/optimize/_nnls.py +20 -21
- scipy/optimize/_nonlin.py +34 -3
- scipy/optimize/_numdiff.py +288 -110
- scipy/optimize/_optimize.py +86 -48
- scipy/optimize/_pava_pybind.cpython-312-darwin.so +0 -0
- scipy/optimize/_remove_redundancy.py +5 -5
- scipy/optimize/_root_scalar.py +1 -1
- scipy/optimize/_shgo.py +6 -0
- scipy/optimize/_shgo_lib/_complex.py +1 -1
- scipy/optimize/_slsqp_py.py +216 -124
- scipy/optimize/_slsqplib.cpython-312-darwin.so +0 -0
- scipy/optimize/_spectral.py +1 -1
- scipy/optimize/_tnc.py +8 -1
- scipy/optimize/_trlib/_trlib.cpython-312-darwin.so +0 -0
- scipy/optimize/_trustregion.py +20 -6
- scipy/optimize/_trustregion_constr/canonical_constraint.py +7 -7
- scipy/optimize/_trustregion_constr/equality_constrained_sqp.py +1 -1
- scipy/optimize/_trustregion_constr/minimize_trustregion_constr.py +11 -3
- scipy/optimize/_trustregion_constr/projections.py +12 -8
- scipy/optimize/_trustregion_constr/qp_subproblem.py +9 -9
- scipy/optimize/_trustregion_constr/tests/test_projections.py +7 -7
- scipy/optimize/_trustregion_constr/tests/test_qp_subproblem.py +77 -77
- scipy/optimize/_trustregion_constr/tr_interior_point.py +5 -5
- scipy/optimize/_trustregion_exact.py +0 -1
- scipy/optimize/_zeros.cpython-312-darwin.so +0 -0
- scipy/optimize/_zeros_py.py +97 -17
- scipy/optimize/cython_optimize/_zeros.cpython-312-darwin.so +0 -0
- scipy/optimize/slsqp.py +0 -1
- scipy/optimize/tests/test__basinhopping.py +1 -1
- scipy/optimize/tests/test__differential_evolution.py +4 -4
- scipy/optimize/tests/test__linprog_clean_inputs.py +5 -3
- scipy/optimize/tests/test__numdiff.py +66 -22
- scipy/optimize/tests/test__remove_redundancy.py +2 -2
- scipy/optimize/tests/test__shgo.py +9 -1
- scipy/optimize/tests/test_bracket.py +36 -46
- scipy/optimize/tests/test_chandrupatla.py +133 -135
- scipy/optimize/tests/test_cobyla.py +74 -45
- scipy/optimize/tests/test_constraints.py +1 -1
- scipy/optimize/tests/test_differentiable_functions.py +226 -6
- scipy/optimize/tests/test_lbfgsb_hessinv.py +22 -0
- scipy/optimize/tests/test_least_squares.py +125 -13
- scipy/optimize/tests/test_linear_assignment.py +3 -3
- scipy/optimize/tests/test_linprog.py +3 -3
- scipy/optimize/tests/test_lsq_linear.py +6 -6
- scipy/optimize/tests/test_minimize_constrained.py +2 -2
- scipy/optimize/tests/test_minpack.py +4 -4
- scipy/optimize/tests/test_nnls.py +43 -3
- scipy/optimize/tests/test_nonlin.py +36 -0
- scipy/optimize/tests/test_optimize.py +95 -17
- scipy/optimize/tests/test_slsqp.py +36 -4
- scipy/optimize/tests/test_zeros.py +34 -1
- scipy/signal/__init__.py +12 -23
- scipy/signal/_delegators.py +568 -0
- scipy/signal/_filter_design.py +459 -241
- scipy/signal/_fir_filter_design.py +262 -90
- scipy/signal/_lti_conversion.py +3 -2
- scipy/signal/_ltisys.py +118 -91
- scipy/signal/_max_len_seq_inner.cpython-312-darwin.so +0 -0
- scipy/signal/_peak_finding_utils.cpython-312-darwin.so +0 -0
- scipy/signal/_polyutils.py +172 -0
- scipy/signal/_short_time_fft.py +519 -70
- scipy/signal/_signal_api.py +30 -0
- scipy/signal/_signaltools.py +719 -399
- scipy/signal/_sigtools.cpython-312-darwin.so +0 -0
- scipy/signal/_sosfilt.cpython-312-darwin.so +0 -0
- scipy/signal/_spectral_py.py +230 -50
- scipy/signal/_spline.cpython-312-darwin.so +0 -0
- scipy/signal/_spline_filters.py +108 -68
- scipy/signal/_support_alternative_backends.py +73 -0
- scipy/signal/_upfirdn.py +4 -1
- scipy/signal/_upfirdn_apply.cpython-312-darwin.so +0 -0
- scipy/signal/_waveforms.py +2 -11
- scipy/signal/_wavelets.py +1 -1
- scipy/signal/fir_filter_design.py +1 -0
- scipy/signal/spline.py +4 -11
- scipy/signal/tests/_scipy_spectral_test_shim.py +2 -171
- scipy/signal/tests/test_bsplines.py +114 -79
- scipy/signal/tests/test_cont2discrete.py +9 -2
- scipy/signal/tests/test_filter_design.py +721 -481
- scipy/signal/tests/test_fir_filter_design.py +332 -140
- scipy/signal/tests/test_savitzky_golay.py +4 -3
- scipy/signal/tests/test_short_time_fft.py +221 -3
- scipy/signal/tests/test_signaltools.py +2144 -1348
- scipy/signal/tests/test_spectral.py +50 -6
- scipy/signal/tests/test_splines.py +161 -96
- scipy/signal/tests/test_upfirdn.py +84 -50
- scipy/signal/tests/test_waveforms.py +20 -0
- scipy/signal/tests/test_windows.py +607 -466
- scipy/signal/windows/_windows.py +287 -148
- scipy/sparse/__init__.py +23 -4
- scipy/sparse/_base.py +270 -108
- scipy/sparse/_bsr.py +7 -4
- scipy/sparse/_compressed.py +59 -231
- scipy/sparse/_construct.py +90 -38
- scipy/sparse/_coo.py +115 -181
- scipy/sparse/_csc.py +4 -4
- scipy/sparse/_csparsetools.cpython-312-darwin.so +0 -0
- scipy/sparse/_csr.py +2 -2
- scipy/sparse/_data.py +48 -48
- scipy/sparse/_dia.py +105 -18
- scipy/sparse/_dok.py +0 -23
- scipy/sparse/_index.py +4 -4
- scipy/sparse/_matrix.py +23 -0
- scipy/sparse/_sparsetools.cpython-312-darwin.so +0 -0
- scipy/sparse/_sputils.py +37 -22
- scipy/sparse/base.py +0 -9
- scipy/sparse/bsr.py +0 -14
- scipy/sparse/compressed.py +0 -23
- scipy/sparse/construct.py +0 -6
- scipy/sparse/coo.py +0 -14
- scipy/sparse/csc.py +0 -3
- scipy/sparse/csgraph/_flow.cpython-312-darwin.so +0 -0
- scipy/sparse/csgraph/_matching.cpython-312-darwin.so +0 -0
- scipy/sparse/csgraph/_min_spanning_tree.cpython-312-darwin.so +0 -0
- scipy/sparse/csgraph/_reordering.cpython-312-darwin.so +0 -0
- scipy/sparse/csgraph/_shortest_path.cpython-312-darwin.so +0 -0
- scipy/sparse/csgraph/_tools.cpython-312-darwin.so +0 -0
- scipy/sparse/csgraph/_traversal.cpython-312-darwin.so +0 -0
- scipy/sparse/csgraph/tests/test_matching.py +14 -2
- scipy/sparse/csgraph/tests/test_pydata_sparse.py +4 -1
- scipy/sparse/csgraph/tests/test_shortest_path.py +83 -27
- scipy/sparse/csr.py +0 -5
- scipy/sparse/data.py +1 -6
- scipy/sparse/dia.py +0 -7
- scipy/sparse/dok.py +0 -10
- scipy/sparse/linalg/_dsolve/_superlu.cpython-312-darwin.so +0 -0
- scipy/sparse/linalg/_dsolve/linsolve.py +9 -0
- scipy/sparse/linalg/_dsolve/tests/test_linsolve.py +35 -28
- scipy/sparse/linalg/_eigen/arpack/_arpack.cpython-312-darwin.so +0 -0
- scipy/sparse/linalg/_eigen/arpack/arpack.py +23 -17
- scipy/sparse/linalg/_eigen/lobpcg/lobpcg.py +6 -6
- scipy/sparse/linalg/_interface.py +17 -18
- scipy/sparse/linalg/_isolve/_gcrotmk.py +4 -4
- scipy/sparse/linalg/_isolve/iterative.py +51 -45
- scipy/sparse/linalg/_isolve/lgmres.py +6 -6
- scipy/sparse/linalg/_isolve/minres.py +5 -5
- scipy/sparse/linalg/_isolve/tfqmr.py +7 -7
- scipy/sparse/linalg/_isolve/utils.py +2 -8
- scipy/sparse/linalg/_matfuncs.py +1 -1
- scipy/sparse/linalg/_norm.py +1 -1
- scipy/sparse/linalg/_propack/_cpropack.cpython-312-darwin.so +0 -0
- scipy/sparse/linalg/_propack/_dpropack.cpython-312-darwin.so +0 -0
- scipy/sparse/linalg/_propack/_spropack.cpython-312-darwin.so +0 -0
- scipy/sparse/linalg/_propack/_zpropack.cpython-312-darwin.so +0 -0
- scipy/sparse/linalg/_special_sparse_arrays.py +39 -38
- scipy/sparse/linalg/tests/test_pydata_sparse.py +14 -0
- scipy/sparse/tests/test_arithmetic1d.py +5 -2
- scipy/sparse/tests/test_base.py +214 -42
- scipy/sparse/tests/test_common1d.py +7 -7
- scipy/sparse/tests/test_construct.py +1 -1
- scipy/sparse/tests/test_coo.py +272 -4
- scipy/sparse/tests/test_sparsetools.py +5 -0
- scipy/sparse/tests/test_sputils.py +36 -7
- scipy/spatial/_ckdtree.cpython-312-darwin.so +0 -0
- scipy/spatial/_distance_pybind.cpython-312-darwin.so +0 -0
- scipy/spatial/_distance_wrap.cpython-312-darwin.so +0 -0
- scipy/spatial/_hausdorff.cpython-312-darwin.so +0 -0
- scipy/spatial/_qhull.cpython-312-darwin.so +0 -0
- scipy/spatial/_voronoi.cpython-312-darwin.so +0 -0
- scipy/spatial/distance.py +49 -42
- scipy/spatial/tests/test_distance.py +15 -1
- scipy/spatial/tests/test_kdtree.py +1 -0
- scipy/spatial/tests/test_qhull.py +7 -2
- scipy/spatial/transform/__init__.py +5 -3
- scipy/spatial/transform/_rigid_transform.cpython-312-darwin.so +0 -0
- scipy/spatial/transform/_rotation.cpython-312-darwin.so +0 -0
- scipy/spatial/transform/tests/test_rigid_transform.py +1221 -0
- scipy/spatial/transform/tests/test_rotation.py +1213 -832
- scipy/spatial/transform/tests/test_rotation_groups.py +3 -3
- scipy/spatial/transform/tests/test_rotation_spline.py +29 -8
- scipy/special/__init__.py +1 -47
- scipy/special/_add_newdocs.py +34 -772
- scipy/special/_basic.py +22 -25
- scipy/special/_comb.cpython-312-darwin.so +0 -0
- scipy/special/_ellip_harm_2.cpython-312-darwin.so +0 -0
- scipy/special/_gufuncs.cpython-312-darwin.so +0 -0
- scipy/special/_logsumexp.py +67 -58
- scipy/special/_orthogonal.pyi +1 -1
- scipy/special/_specfun.cpython-312-darwin.so +0 -0
- scipy/special/_special_ufuncs.cpython-312-darwin.so +0 -0
- scipy/special/_spherical_bessel.py +4 -4
- scipy/special/_support_alternative_backends.py +212 -119
- scipy/special/_test_internal.cpython-312-darwin.so +0 -0
- scipy/special/_testutils.py +4 -4
- scipy/special/_ufuncs.cpython-312-darwin.so +0 -0
- scipy/special/_ufuncs.pyi +1 -0
- scipy/special/_ufuncs.pyx +215 -1400
- scipy/special/_ufuncs_cxx.cpython-312-darwin.so +0 -0
- scipy/special/_ufuncs_cxx.pxd +2 -15
- scipy/special/_ufuncs_cxx.pyx +5 -44
- scipy/special/_ufuncs_cxx_defs.h +2 -16
- scipy/special/_ufuncs_defs.h +0 -8
- scipy/special/cython_special.cpython-312-darwin.so +0 -0
- scipy/special/cython_special.pxd +1 -1
- scipy/special/tests/_cython_examples/meson.build +10 -1
- scipy/special/tests/test_basic.py +153 -20
- scipy/special/tests/test_boost_ufuncs.py +3 -0
- scipy/special/tests/test_cdflib.py +35 -11
- scipy/special/tests/test_gammainc.py +16 -0
- scipy/special/tests/test_hyp2f1.py +2 -2
- scipy/special/tests/test_log1mexp.py +85 -0
- scipy/special/tests/test_logsumexp.py +206 -64
- scipy/special/tests/test_mpmath.py +1 -0
- scipy/special/tests/test_nan_inputs.py +1 -1
- scipy/special/tests/test_orthogonal.py +17 -18
- scipy/special/tests/test_sf_error.py +3 -2
- scipy/special/tests/test_sph_harm.py +6 -7
- scipy/special/tests/test_support_alternative_backends.py +211 -76
- scipy/stats/__init__.py +4 -1
- scipy/stats/_ansari_swilk_statistics.cpython-312-darwin.so +0 -0
- scipy/stats/_axis_nan_policy.py +5 -12
- scipy/stats/_biasedurn.cpython-312-darwin.so +0 -0
- scipy/stats/_continued_fraction.py +387 -0
- scipy/stats/_continuous_distns.py +277 -310
- scipy/stats/_correlation.py +1 -1
- scipy/stats/_covariance.py +6 -3
- scipy/stats/_discrete_distns.py +39 -32
- scipy/stats/_distn_infrastructure.py +39 -12
- scipy/stats/_distribution_infrastructure.py +900 -238
- scipy/stats/_entropy.py +9 -10
- scipy/{_lib → stats}/_finite_differences.py +1 -1
- scipy/stats/_hypotests.py +83 -50
- scipy/stats/_kde.py +53 -49
- scipy/stats/_ksstats.py +1 -1
- scipy/stats/_levy_stable/__init__.py +7 -15
- scipy/stats/_levy_stable/levyst.cpython-312-darwin.so +0 -0
- scipy/stats/_morestats.py +118 -73
- scipy/stats/_mstats_basic.py +13 -17
- scipy/stats/_mstats_extras.py +8 -8
- scipy/stats/_multivariate.py +89 -113
- scipy/stats/_new_distributions.py +97 -20
- scipy/stats/_page_trend_test.py +12 -5
- scipy/stats/_probability_distribution.py +265 -43
- scipy/stats/_qmc.py +14 -9
- scipy/stats/_qmc_cy.cpython-312-darwin.so +0 -0
- scipy/stats/_qmvnt.py +16 -95
- scipy/stats/_qmvnt_cy.cpython-312-darwin.so +0 -0
- scipy/stats/_quantile.py +335 -0
- scipy/stats/_rcont/rcont.cpython-312-darwin.so +0 -0
- scipy/stats/_resampling.py +4 -29
- scipy/stats/_sampling.py +1 -1
- scipy/stats/_sobol.cpython-312-darwin.so +0 -0
- scipy/stats/_stats.cpython-312-darwin.so +0 -0
- scipy/stats/_stats_mstats_common.py +21 -2
- scipy/stats/_stats_py.py +550 -476
- scipy/stats/_stats_pythran.cpython-312-darwin.so +0 -0
- scipy/stats/_unuran/unuran_wrapper.cpython-312-darwin.so +0 -0
- scipy/stats/_unuran/unuran_wrapper.pyi +2 -1
- scipy/stats/_variation.py +6 -8
- scipy/stats/_wilcoxon.py +13 -7
- scipy/stats/tests/common_tests.py +6 -4
- scipy/stats/tests/test_axis_nan_policy.py +62 -24
- scipy/stats/tests/test_continued_fraction.py +173 -0
- scipy/stats/tests/test_continuous.py +379 -60
- scipy/stats/tests/test_continuous_basic.py +18 -12
- scipy/stats/tests/test_discrete_basic.py +14 -8
- scipy/stats/tests/test_discrete_distns.py +16 -16
- scipy/stats/tests/test_distributions.py +95 -75
- scipy/stats/tests/test_entropy.py +40 -48
- scipy/stats/tests/test_fit.py +4 -3
- scipy/stats/tests/test_hypotests.py +153 -24
- scipy/stats/tests/test_kdeoth.py +109 -41
- scipy/stats/tests/test_marray.py +289 -0
- scipy/stats/tests/test_morestats.py +79 -47
- scipy/stats/tests/test_mstats_basic.py +3 -3
- scipy/stats/tests/test_multivariate.py +434 -83
- scipy/stats/tests/test_qmc.py +13 -10
- scipy/stats/tests/test_quantile.py +199 -0
- scipy/stats/tests/test_rank.py +119 -112
- scipy/stats/tests/test_resampling.py +47 -56
- scipy/stats/tests/test_sampling.py +9 -4
- scipy/stats/tests/test_stats.py +799 -939
- scipy/stats/tests/test_variation.py +8 -6
- scipy/version.py +2 -2
- {scipy-1.15.3.dist-info → scipy-1.16.0rc2.dist-info}/LICENSE.txt +4 -4
- {scipy-1.15.3.dist-info → scipy-1.16.0rc2.dist-info}/METADATA +11 -11
- {scipy-1.15.3.dist-info → scipy-1.16.0rc2.dist-info}/RECORD +561 -568
- scipy-1.16.0rc2.dist-info/WHEEL +6 -0
- scipy/_lib/array_api_extra/_funcs.py +0 -484
- scipy/_lib/array_api_extra/_typing.py +0 -8
- scipy/interpolate/_bspl.cpython-312-darwin.so +0 -0
- scipy/optimize/_cobyla.cpython-312-darwin.so +0 -0
- scipy/optimize/_cython_nnls.cpython-312-darwin.so +0 -0
- scipy/optimize/_slsqp.cpython-312-darwin.so +0 -0
- scipy/spatial/qhull_src/COPYING.txt +0 -38
- scipy/special/libsf_error_state.dylib +0 -0
- scipy/special/tests/test_log_softmax.py +0 -109
- scipy/special/tests/test_xsf_cuda.py +0 -114
- scipy/special/xsf/binom.h +0 -89
- scipy/special/xsf/cdflib.h +0 -100
- scipy/special/xsf/cephes/airy.h +0 -307
- scipy/special/xsf/cephes/besselpoly.h +0 -51
- scipy/special/xsf/cephes/beta.h +0 -257
- scipy/special/xsf/cephes/cbrt.h +0 -131
- scipy/special/xsf/cephes/chbevl.h +0 -85
- scipy/special/xsf/cephes/chdtr.h +0 -193
- scipy/special/xsf/cephes/const.h +0 -87
- scipy/special/xsf/cephes/ellie.h +0 -293
- scipy/special/xsf/cephes/ellik.h +0 -251
- scipy/special/xsf/cephes/ellpe.h +0 -107
- scipy/special/xsf/cephes/ellpk.h +0 -117
- scipy/special/xsf/cephes/expn.h +0 -260
- scipy/special/xsf/cephes/gamma.h +0 -398
- scipy/special/xsf/cephes/hyp2f1.h +0 -596
- scipy/special/xsf/cephes/hyperg.h +0 -361
- scipy/special/xsf/cephes/i0.h +0 -149
- scipy/special/xsf/cephes/i1.h +0 -158
- scipy/special/xsf/cephes/igam.h +0 -421
- scipy/special/xsf/cephes/igam_asymp_coeff.h +0 -195
- scipy/special/xsf/cephes/igami.h +0 -313
- scipy/special/xsf/cephes/j0.h +0 -225
- scipy/special/xsf/cephes/j1.h +0 -198
- scipy/special/xsf/cephes/jv.h +0 -715
- scipy/special/xsf/cephes/k0.h +0 -164
- scipy/special/xsf/cephes/k1.h +0 -163
- scipy/special/xsf/cephes/kn.h +0 -243
- scipy/special/xsf/cephes/lanczos.h +0 -112
- scipy/special/xsf/cephes/ndtr.h +0 -275
- scipy/special/xsf/cephes/poch.h +0 -85
- scipy/special/xsf/cephes/polevl.h +0 -167
- scipy/special/xsf/cephes/psi.h +0 -194
- scipy/special/xsf/cephes/rgamma.h +0 -111
- scipy/special/xsf/cephes/scipy_iv.h +0 -811
- scipy/special/xsf/cephes/shichi.h +0 -248
- scipy/special/xsf/cephes/sici.h +0 -224
- scipy/special/xsf/cephes/sindg.h +0 -221
- scipy/special/xsf/cephes/tandg.h +0 -139
- scipy/special/xsf/cephes/trig.h +0 -58
- scipy/special/xsf/cephes/unity.h +0 -186
- scipy/special/xsf/cephes/zeta.h +0 -172
- scipy/special/xsf/config.h +0 -304
- scipy/special/xsf/digamma.h +0 -205
- scipy/special/xsf/error.h +0 -57
- scipy/special/xsf/evalpoly.h +0 -47
- scipy/special/xsf/expint.h +0 -266
- scipy/special/xsf/hyp2f1.h +0 -694
- scipy/special/xsf/iv_ratio.h +0 -173
- scipy/special/xsf/lambertw.h +0 -150
- scipy/special/xsf/loggamma.h +0 -163
- scipy/special/xsf/sici.h +0 -200
- scipy/special/xsf/tools.h +0 -427
- scipy/special/xsf/trig.h +0 -164
- scipy/special/xsf/wright_bessel.h +0 -843
- scipy/special/xsf/zlog1.h +0 -35
- scipy/stats/_mvn.cpython-312-darwin.so +0 -0
- scipy-1.15.3.dist-info/WHEEL +0 -4
@@ -0,0 +1,357 @@
|
|
1
|
+
"""Public API Functions."""
|
2
|
+
|
3
|
+
from __future__ import annotations
|
4
|
+
|
5
|
+
import math
|
6
|
+
from collections.abc import Callable, Sequence
|
7
|
+
from functools import partial, wraps
|
8
|
+
from types import ModuleType
|
9
|
+
from typing import TYPE_CHECKING, Any, ParamSpec, TypeAlias, cast, overload
|
10
|
+
|
11
|
+
from ._funcs import broadcast_shapes
|
12
|
+
from ._utils import _compat
|
13
|
+
from ._utils._compat import (
|
14
|
+
array_namespace,
|
15
|
+
is_dask_namespace,
|
16
|
+
is_jax_namespace,
|
17
|
+
)
|
18
|
+
from ._utils._helpers import is_python_scalar
|
19
|
+
from ._utils._typing import Array, DType
|
20
|
+
|
21
|
+
if TYPE_CHECKING: # pragma: no cover
|
22
|
+
import numpy as np
|
23
|
+
from numpy.typing import ArrayLike
|
24
|
+
|
25
|
+
NumPyObject: TypeAlias = np.ndarray[Any, Any] | np.generic # type: ignore[explicit-any]
|
26
|
+
else:
|
27
|
+
# Sphinx hack
|
28
|
+
NumPyObject = Any
|
29
|
+
|
30
|
+
P = ParamSpec("P")
|
31
|
+
|
32
|
+
|
33
|
+
@overload
|
34
|
+
def lazy_apply( # type: ignore[decorated-any, valid-type]
|
35
|
+
func: Callable[P, Array | ArrayLike],
|
36
|
+
*args: Array | complex | None,
|
37
|
+
shape: tuple[int | None, ...] | None = None,
|
38
|
+
dtype: DType | None = None,
|
39
|
+
as_numpy: bool = False,
|
40
|
+
xp: ModuleType | None = None,
|
41
|
+
**kwargs: P.kwargs, # pyright: ignore[reportGeneralTypeIssues]
|
42
|
+
) -> Array: ... # numpydoc ignore=GL08
|
43
|
+
|
44
|
+
|
45
|
+
@overload
|
46
|
+
def lazy_apply( # type: ignore[decorated-any, valid-type]
|
47
|
+
func: Callable[P, Sequence[Array | ArrayLike]],
|
48
|
+
*args: Array | complex | None,
|
49
|
+
shape: Sequence[tuple[int | None, ...]],
|
50
|
+
dtype: Sequence[DType] | None = None,
|
51
|
+
as_numpy: bool = False,
|
52
|
+
xp: ModuleType | None = None,
|
53
|
+
**kwargs: P.kwargs, # pyright: ignore[reportGeneralTypeIssues]
|
54
|
+
) -> tuple[Array, ...]: ... # numpydoc ignore=GL08
|
55
|
+
|
56
|
+
|
57
|
+
def lazy_apply( # type: ignore[valid-type] # numpydoc ignore=GL07,SA04
|
58
|
+
func: Callable[P, Array | ArrayLike | Sequence[Array | ArrayLike]],
|
59
|
+
*args: Array | complex | None,
|
60
|
+
shape: tuple[int | None, ...] | Sequence[tuple[int | None, ...]] | None = None,
|
61
|
+
dtype: DType | Sequence[DType] | None = None,
|
62
|
+
as_numpy: bool = False,
|
63
|
+
xp: ModuleType | None = None,
|
64
|
+
**kwargs: P.kwargs, # pyright: ignore[reportGeneralTypeIssues]
|
65
|
+
) -> Array | tuple[Array, ...]:
|
66
|
+
"""
|
67
|
+
Lazily apply an eager function.
|
68
|
+
|
69
|
+
If the backend of the input arrays is lazy, e.g. Dask or jitted JAX, the execution
|
70
|
+
of the function is delayed until the graph is materialized; if it's eager, the
|
71
|
+
function is executed immediately.
|
72
|
+
|
73
|
+
Parameters
|
74
|
+
----------
|
75
|
+
func : callable
|
76
|
+
The function to apply.
|
77
|
+
|
78
|
+
It must accept one or more array API compliant arrays as positional arguments.
|
79
|
+
If `as_numpy=True`, inputs are converted to NumPy before they are passed to
|
80
|
+
`func`.
|
81
|
+
It must return either a single array-like or a sequence of array-likes.
|
82
|
+
|
83
|
+
`func` must be a pure function, i.e. without side effects, as depending on the
|
84
|
+
backend it may be executed more than once or never.
|
85
|
+
*args : Array | int | float | complex | bool | None
|
86
|
+
One or more Array API compliant arrays, Python scalars, or None's.
|
87
|
+
|
88
|
+
If `as_numpy=True`, you need to be able to apply :func:`numpy.asarray` to
|
89
|
+
non-None args to convert them to NumPy; read notes below about specific
|
90
|
+
backends.
|
91
|
+
shape : tuple[int | None, ...] | Sequence[tuple[int | None, ...]], optional
|
92
|
+
Output shape or sequence of output shapes, one for each output of `func`.
|
93
|
+
Default: assume single output and broadcast shapes of the input arrays.
|
94
|
+
dtype : DType | Sequence[DType], optional
|
95
|
+
Output dtype or sequence of output dtypes, one for each output of `func`.
|
96
|
+
dtype(s) must belong to the same array namespace as the input arrays.
|
97
|
+
Default: infer the result type(s) from the input arrays.
|
98
|
+
as_numpy : bool, optional
|
99
|
+
If True, convert the input arrays to NumPy before passing them to `func`.
|
100
|
+
This is particularly useful to make NumPy-only functions, e.g. written in Cython
|
101
|
+
or Numba, work transparently with array API-compliant arrays.
|
102
|
+
Default: False.
|
103
|
+
xp : array_namespace, optional
|
104
|
+
The standard-compatible namespace for `args`. Default: infer.
|
105
|
+
**kwargs : Any, optional
|
106
|
+
Additional keyword arguments to pass verbatim to `func`.
|
107
|
+
They cannot contain Array objects.
|
108
|
+
|
109
|
+
Returns
|
110
|
+
-------
|
111
|
+
Array | tuple[Array, ...]
|
112
|
+
The result(s) of `func` applied to the input arrays, wrapped in the same
|
113
|
+
array namespace as the inputs.
|
114
|
+
If shape is omitted or a single `tuple[int | None, ...]`, return a single array.
|
115
|
+
Otherwise, return a tuple of arrays.
|
116
|
+
|
117
|
+
Notes
|
118
|
+
-----
|
119
|
+
JAX
|
120
|
+
This allows applying eager functions to jitted JAX arrays, which are lazy.
|
121
|
+
The function won't be applied until the JAX array is materialized.
|
122
|
+
When running inside ``jax.jit``, `shape` must be fully known, i.e. it cannot
|
123
|
+
contain any `None` elements.
|
124
|
+
|
125
|
+
.. warning::
|
126
|
+
|
127
|
+
`func` must never raise inside ``jax.jit``, as the resulting behavior is
|
128
|
+
undefined.
|
129
|
+
|
130
|
+
Using this with `as_numpy=False` is particularly useful to apply non-jittable
|
131
|
+
JAX functions to arrays on GPU devices.
|
132
|
+
If ``as_numpy=True``, the :doc:`jax:transfer_guard` may prevent arrays on a GPU
|
133
|
+
device from being transferred back to CPU. This is treated as an implicit
|
134
|
+
transfer.
|
135
|
+
|
136
|
+
PyTorch, CuPy
|
137
|
+
If ``as_numpy=True``, these backends raise by default if you attempt to convert
|
138
|
+
arrays on a GPU device to NumPy.
|
139
|
+
|
140
|
+
Sparse
|
141
|
+
If ``as_numpy=True``, by default sparse prevents implicit densification through
|
142
|
+
:func:`numpy.asarray`. `This safety mechanism can be disabled
|
143
|
+
<https://sparse.pydata.org/en/stable/operations.html#package-configuration>`_.
|
144
|
+
|
145
|
+
Dask
|
146
|
+
This allows applying eager functions to Dask arrays.
|
147
|
+
The Dask graph won't be computed until the user calls ``compute()`` or
|
148
|
+
``persist()`` down the line.
|
149
|
+
|
150
|
+
The function name will be prominently visible on the user-facing Dask
|
151
|
+
dashboard and on Prometheus metrics, so it is recommended for it to be
|
152
|
+
meaningful.
|
153
|
+
|
154
|
+
`lazy_apply` doesn't know if `func` reduces along any axes; also, shape
|
155
|
+
changes are non-trivial in chunked Dask arrays. For these reasons, all inputs
|
156
|
+
will be rechunked into a single chunk.
|
157
|
+
|
158
|
+
.. warning::
|
159
|
+
|
160
|
+
The whole operation needs to fit in memory all at once on a single worker.
|
161
|
+
|
162
|
+
The outputs will also be returned as a single chunk and you should consider
|
163
|
+
rechunking them into smaller chunks afterwards.
|
164
|
+
|
165
|
+
If you want to distribute the calculation across multiple workers, you
|
166
|
+
should use :func:`dask.array.map_blocks`, :func:`dask.array.map_overlap`,
|
167
|
+
:func:`dask.array.blockwise`, or a native Dask wrapper instead of
|
168
|
+
`lazy_apply`.
|
169
|
+
|
170
|
+
Dask wrapping around other backends
|
171
|
+
If ``as_numpy=False``, `func` will receive in input eager arrays of the meta
|
172
|
+
namespace, as defined by the ``._meta`` attribute of the input Dask arrays.
|
173
|
+
The outputs of `func` will be wrapped by the meta namespace, and then wrapped
|
174
|
+
again by Dask.
|
175
|
+
|
176
|
+
Raises
|
177
|
+
------
|
178
|
+
ValueError
|
179
|
+
When ``xp=jax.numpy``, the output `shape` is unknown (it contains ``None`` on
|
180
|
+
one or more axes) and this function was called inside ``jax.jit``.
|
181
|
+
RuntimeError
|
182
|
+
When ``xp=sparse`` and auto-densification is disabled.
|
183
|
+
Exception (backend-specific)
|
184
|
+
When the backend disallows implicit device to host transfers and the input
|
185
|
+
arrays are on a non-CPU device, e.g. on GPU.
|
186
|
+
|
187
|
+
See Also
|
188
|
+
--------
|
189
|
+
jax.transfer_guard
|
190
|
+
jax.pure_callback
|
191
|
+
dask.array.map_blocks
|
192
|
+
dask.array.map_overlap
|
193
|
+
dask.array.blockwise
|
194
|
+
"""
|
195
|
+
args_not_none = [arg for arg in args if arg is not None]
|
196
|
+
array_args = [arg for arg in args_not_none if not is_python_scalar(arg)]
|
197
|
+
if not array_args:
|
198
|
+
msg = "Must have at least one argument array"
|
199
|
+
raise ValueError(msg)
|
200
|
+
if xp is None:
|
201
|
+
xp = array_namespace(*args)
|
202
|
+
|
203
|
+
# Normalize and validate shape and dtype
|
204
|
+
shapes: list[tuple[int | None, ...]]
|
205
|
+
dtypes: list[DType]
|
206
|
+
multi_output = False
|
207
|
+
|
208
|
+
if shape is None:
|
209
|
+
shapes = [broadcast_shapes(*(arg.shape for arg in array_args))]
|
210
|
+
elif all(isinstance(s, int | None) for s in shape):
|
211
|
+
# Do not test for shape to be a tuple
|
212
|
+
# https://github.com/data-apis/array-api/issues/891#issuecomment-2637430522
|
213
|
+
shapes = [cast(tuple[int | None, ...], shape)]
|
214
|
+
else:
|
215
|
+
shapes = list(shape) # type: ignore[arg-type] # pyright: ignore[reportAssignmentType]
|
216
|
+
multi_output = True
|
217
|
+
|
218
|
+
if dtype is None:
|
219
|
+
dtypes = [xp.result_type(*args_not_none)] * len(shapes)
|
220
|
+
elif multi_output:
|
221
|
+
if not isinstance(dtype, Sequence):
|
222
|
+
msg = "Got multiple shapes but only one dtype"
|
223
|
+
raise ValueError(msg)
|
224
|
+
dtypes = list(dtype) # pyright: ignore[reportUnknownArgumentType]
|
225
|
+
else:
|
226
|
+
if isinstance(dtype, Sequence):
|
227
|
+
msg = "Got single shape but multiple dtypes"
|
228
|
+
raise ValueError(msg)
|
229
|
+
|
230
|
+
dtypes = [dtype]
|
231
|
+
|
232
|
+
if len(shapes) != len(dtypes):
|
233
|
+
msg = f"Got {len(shapes)} shapes and {len(dtypes)} dtypes"
|
234
|
+
raise ValueError(msg)
|
235
|
+
del shape
|
236
|
+
del dtype
|
237
|
+
# End of shape and dtype parsing
|
238
|
+
|
239
|
+
# Backend-specific branches
|
240
|
+
if is_dask_namespace(xp):
|
241
|
+
import dask
|
242
|
+
|
243
|
+
metas: list[Array] = [arg._meta for arg in array_args] # pylint: disable=protected-access # pyright: ignore[reportAttributeAccessIssue]
|
244
|
+
meta_xp = array_namespace(*metas)
|
245
|
+
|
246
|
+
wrapped = dask.delayed( # type: ignore[attr-defined] # pyright: ignore[reportPrivateImportUsage]
|
247
|
+
_lazy_apply_wrapper(func, as_numpy, multi_output, meta_xp),
|
248
|
+
pure=True,
|
249
|
+
)
|
250
|
+
# This finalizes each arg, which is the same as arg.rechunk(-1).
|
251
|
+
# Please read docstring above for why we're not using
|
252
|
+
# dask.array.map_blocks or dask.array.blockwise!
|
253
|
+
delayed_out = wrapped(*args, **kwargs)
|
254
|
+
|
255
|
+
out = tuple(
|
256
|
+
xp.from_delayed(
|
257
|
+
delayed_out[i], # pyright: ignore[reportIndexIssue]
|
258
|
+
# Dask's unknown shapes diverge from the Array API specification
|
259
|
+
shape=tuple(math.nan if s is None else s for s in shape),
|
260
|
+
dtype=dtype,
|
261
|
+
meta=metas[0],
|
262
|
+
)
|
263
|
+
for i, (shape, dtype) in enumerate(zip(shapes, dtypes, strict=True))
|
264
|
+
)
|
265
|
+
|
266
|
+
elif is_jax_namespace(xp) and _is_jax_jit_enabled(xp):
|
267
|
+
# Delay calling func with jax.pure_callback, which will forward to func eager
|
268
|
+
# JAX arrays. Do not use jax.pure_callback when running outside of the JIT,
|
269
|
+
# as it does not support raising exceptions:
|
270
|
+
# https://github.com/jax-ml/jax/issues/26102
|
271
|
+
import jax
|
272
|
+
|
273
|
+
if any(None in shape for shape in shapes):
|
274
|
+
msg = "Output shape must be fully known when running inside jax.jit"
|
275
|
+
raise ValueError(msg)
|
276
|
+
|
277
|
+
# Shield kwargs from being coerced into JAX arrays.
|
278
|
+
# jax.pure_callback calls jax.jit under the hood, but without the chance of
|
279
|
+
# passing static_argnames / static_argnums.
|
280
|
+
wrapped = _lazy_apply_wrapper(
|
281
|
+
partial(func, **kwargs), as_numpy, multi_output, xp
|
282
|
+
)
|
283
|
+
|
284
|
+
# suppress unused-ignore to run mypy in -e lint as well as -e dev
|
285
|
+
out = cast( # type: ignore[bad-cast,unused-ignore]
|
286
|
+
tuple[Array, ...],
|
287
|
+
jax.pure_callback(
|
288
|
+
wrapped,
|
289
|
+
tuple(
|
290
|
+
jax.ShapeDtypeStruct(shape, dtype) # pyright: ignore[reportUnknownArgumentType]
|
291
|
+
for shape, dtype in zip(shapes, dtypes, strict=True)
|
292
|
+
),
|
293
|
+
*args,
|
294
|
+
),
|
295
|
+
)
|
296
|
+
|
297
|
+
else:
|
298
|
+
# Eager backends, including non-jitted JAX
|
299
|
+
wrapped = _lazy_apply_wrapper(func, as_numpy, multi_output, xp)
|
300
|
+
out = wrapped(*args, **kwargs)
|
301
|
+
|
302
|
+
return out if multi_output else out[0]
|
303
|
+
|
304
|
+
|
305
|
+
def _is_jax_jit_enabled(xp: ModuleType) -> bool: # numpydoc ignore=PR01,RT01
|
306
|
+
"""Return True if this function is being called inside ``jax.jit``."""
|
307
|
+
import jax # pylint: disable=import-outside-toplevel
|
308
|
+
|
309
|
+
x = xp.asarray(False)
|
310
|
+
try:
|
311
|
+
return bool(x)
|
312
|
+
except jax.errors.TracerBoolConversionError:
|
313
|
+
return True
|
314
|
+
|
315
|
+
|
316
|
+
def _lazy_apply_wrapper( # type: ignore[explicit-any] # numpydoc ignore=PR01,RT01
|
317
|
+
func: Callable[..., Array | ArrayLike | Sequence[Array | ArrayLike]],
|
318
|
+
as_numpy: bool,
|
319
|
+
multi_output: bool,
|
320
|
+
xp: ModuleType,
|
321
|
+
) -> Callable[..., tuple[Array, ...]]:
|
322
|
+
"""
|
323
|
+
Helper of `lazy_apply`.
|
324
|
+
|
325
|
+
Given a function that accepts one or more arrays as positional arguments and returns
|
326
|
+
a single array-like or a sequence of array-likes, return a function that accepts the
|
327
|
+
same number of Array API arrays and always returns a tuple of Array API array.
|
328
|
+
|
329
|
+
Any keyword arguments are passed through verbatim to the wrapped function.
|
330
|
+
"""
|
331
|
+
|
332
|
+
# On Dask, @wraps causes the graph key to contain the wrapped function's name
|
333
|
+
@wraps(func)
|
334
|
+
def wrapper( # type: ignore[decorated-any,explicit-any]
|
335
|
+
*args: Array | complex | None, **kwargs: Any
|
336
|
+
) -> tuple[Array, ...]: # numpydoc ignore=GL08
|
337
|
+
args_list = []
|
338
|
+
device = None
|
339
|
+
for arg in args:
|
340
|
+
if arg is not None and not is_python_scalar(arg):
|
341
|
+
if device is None:
|
342
|
+
device = _compat.device(arg)
|
343
|
+
if as_numpy:
|
344
|
+
import numpy as np
|
345
|
+
|
346
|
+
arg = cast(Array, np.asarray(arg)) # type: ignore[bad-cast] # noqa: PLW2901
|
347
|
+
args_list.append(arg)
|
348
|
+
assert device is not None
|
349
|
+
|
350
|
+
out = func(*args_list, **kwargs)
|
351
|
+
|
352
|
+
if multi_output:
|
353
|
+
assert isinstance(out, Sequence)
|
354
|
+
return tuple(xp.asarray(o, device=device) for o in out)
|
355
|
+
return (xp.asarray(out, device=device),)
|
356
|
+
|
357
|
+
return wrapper
|
@@ -0,0 +1,278 @@
|
|
1
|
+
"""
|
2
|
+
Testing utilities.
|
3
|
+
|
4
|
+
Note that this is private API; don't expect it to be stable.
|
5
|
+
See also ..testing for public testing utilities.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from __future__ import annotations
|
9
|
+
|
10
|
+
import math
|
11
|
+
from types import ModuleType
|
12
|
+
from typing import Any, cast
|
13
|
+
|
14
|
+
import numpy as np
|
15
|
+
import pytest
|
16
|
+
|
17
|
+
from ._utils._compat import (
|
18
|
+
array_namespace,
|
19
|
+
is_array_api_strict_namespace,
|
20
|
+
is_cupy_namespace,
|
21
|
+
is_dask_namespace,
|
22
|
+
is_jax_namespace,
|
23
|
+
is_numpy_namespace,
|
24
|
+
is_pydata_sparse_namespace,
|
25
|
+
is_torch_namespace,
|
26
|
+
to_device,
|
27
|
+
)
|
28
|
+
from ._utils._typing import Array, Device
|
29
|
+
|
30
|
+
__all__ = ["as_numpy_array", "xp_assert_close", "xp_assert_equal", "xp_assert_less"]
|
31
|
+
|
32
|
+
|
33
|
+
def _check_ns_shape_dtype(
|
34
|
+
actual: Array,
|
35
|
+
desired: Array,
|
36
|
+
check_dtype: bool,
|
37
|
+
check_shape: bool,
|
38
|
+
check_scalar: bool,
|
39
|
+
) -> ModuleType: # numpydoc ignore=RT03
|
40
|
+
"""
|
41
|
+
Assert that namespace, shape and dtype of the two arrays match.
|
42
|
+
|
43
|
+
Parameters
|
44
|
+
----------
|
45
|
+
actual : Array
|
46
|
+
The array produced by the tested function.
|
47
|
+
desired : Array
|
48
|
+
The expected array (typically hardcoded).
|
49
|
+
check_dtype, check_shape : bool, default: True
|
50
|
+
Whether to check agreement between actual and desired dtypes and shapes
|
51
|
+
check_scalar : bool, default: False
|
52
|
+
NumPy only: whether to check agreement between actual and desired types -
|
53
|
+
0d array vs scalar.
|
54
|
+
|
55
|
+
Returns
|
56
|
+
-------
|
57
|
+
Arrays namespace.
|
58
|
+
"""
|
59
|
+
actual_xp = array_namespace(actual) # Raises on scalars and lists
|
60
|
+
desired_xp = array_namespace(desired)
|
61
|
+
|
62
|
+
msg = f"namespaces do not match: {actual_xp} != f{desired_xp}"
|
63
|
+
assert actual_xp == desired_xp, msg
|
64
|
+
|
65
|
+
if check_shape:
|
66
|
+
actual_shape = actual.shape
|
67
|
+
desired_shape = desired.shape
|
68
|
+
if is_dask_namespace(desired_xp):
|
69
|
+
# Dask uses nan instead of None for unknown shapes
|
70
|
+
if any(math.isnan(i) for i in cast(tuple[float, ...], actual_shape)):
|
71
|
+
actual_shape = actual.compute().shape # type: ignore[attr-defined] # pyright: ignore[reportAttributeAccessIssue]
|
72
|
+
if any(math.isnan(i) for i in cast(tuple[float, ...], desired_shape)):
|
73
|
+
desired_shape = desired.compute().shape # type: ignore[attr-defined] # pyright: ignore[reportAttributeAccessIssue]
|
74
|
+
|
75
|
+
msg = f"shapes do not match: {actual_shape} != f{desired_shape}"
|
76
|
+
assert actual_shape == desired_shape, msg
|
77
|
+
|
78
|
+
if check_dtype:
|
79
|
+
msg = f"dtypes do not match: {actual.dtype} != {desired.dtype}"
|
80
|
+
assert actual.dtype == desired.dtype, msg
|
81
|
+
|
82
|
+
if is_numpy_namespace(actual_xp) and check_scalar:
|
83
|
+
# only NumPy distinguishes between scalars and arrays; we do if check_scalar.
|
84
|
+
_msg = (
|
85
|
+
"array-ness does not match:\n Actual: "
|
86
|
+
f"{type(actual)}\n Desired: {type(desired)}"
|
87
|
+
)
|
88
|
+
assert np.isscalar(actual) == np.isscalar(desired), _msg
|
89
|
+
|
90
|
+
return desired_xp
|
91
|
+
|
92
|
+
|
93
|
+
def as_numpy_array(array: Array, *, xp: ModuleType) -> np.typing.NDArray[Any]: # type: ignore[explicit-any]
|
94
|
+
"""
|
95
|
+
Convert array to NumPy, bypassing GPU-CPU transfer guards and densification guards.
|
96
|
+
"""
|
97
|
+
if is_cupy_namespace(xp):
|
98
|
+
return xp.asnumpy(array)
|
99
|
+
if is_pydata_sparse_namespace(xp):
|
100
|
+
return array.todense() # type: ignore[attr-defined] # pyright: ignore[reportAttributeAccessIssue]
|
101
|
+
|
102
|
+
if is_torch_namespace(xp):
|
103
|
+
array = to_device(array, "cpu")
|
104
|
+
if is_array_api_strict_namespace(xp):
|
105
|
+
cpu: Device = xp.Device("CPU_DEVICE")
|
106
|
+
array = to_device(array, cpu)
|
107
|
+
if is_jax_namespace(xp):
|
108
|
+
import jax
|
109
|
+
|
110
|
+
# Note: only needed if the transfer guard is enabled
|
111
|
+
cpu = cast(Device, jax.devices("cpu")[0])
|
112
|
+
array = to_device(array, cpu)
|
113
|
+
|
114
|
+
return np.asarray(array)
|
115
|
+
|
116
|
+
|
117
|
+
def xp_assert_equal(
|
118
|
+
actual: Array,
|
119
|
+
desired: Array,
|
120
|
+
*,
|
121
|
+
err_msg: str = "",
|
122
|
+
check_dtype: bool = True,
|
123
|
+
check_shape: bool = True,
|
124
|
+
check_scalar: bool = False,
|
125
|
+
) -> None:
|
126
|
+
"""
|
127
|
+
Array-API compatible version of `np.testing.assert_array_equal`.
|
128
|
+
|
129
|
+
Parameters
|
130
|
+
----------
|
131
|
+
actual : Array
|
132
|
+
The array produced by the tested function.
|
133
|
+
desired : Array
|
134
|
+
The expected array (typically hardcoded).
|
135
|
+
err_msg : str, optional
|
136
|
+
Error message to display on failure.
|
137
|
+
check_dtype, check_shape : bool, default: True
|
138
|
+
Whether to check agreement between actual and desired dtypes and shapes
|
139
|
+
check_scalar : bool, default: False
|
140
|
+
NumPy only: whether to check agreement between actual and desired types -
|
141
|
+
0d array vs scalar.
|
142
|
+
|
143
|
+
See Also
|
144
|
+
--------
|
145
|
+
xp_assert_close : Similar function for inexact equality checks.
|
146
|
+
numpy.testing.assert_array_equal : Similar function for NumPy arrays.
|
147
|
+
"""
|
148
|
+
xp = _check_ns_shape_dtype(actual, desired, check_dtype, check_shape, check_scalar)
|
149
|
+
actual_np = as_numpy_array(actual, xp=xp)
|
150
|
+
desired_np = as_numpy_array(desired, xp=xp)
|
151
|
+
np.testing.assert_array_equal(actual_np, desired_np, err_msg=err_msg)
|
152
|
+
|
153
|
+
|
154
|
+
def xp_assert_less(
|
155
|
+
x: Array,
|
156
|
+
y: Array,
|
157
|
+
*,
|
158
|
+
err_msg: str = "",
|
159
|
+
check_dtype: bool = True,
|
160
|
+
check_shape: bool = True,
|
161
|
+
check_scalar: bool = False,
|
162
|
+
) -> None:
|
163
|
+
"""
|
164
|
+
Array-API compatible version of `np.testing.assert_array_less`.
|
165
|
+
|
166
|
+
Parameters
|
167
|
+
----------
|
168
|
+
x, y : Array
|
169
|
+
The arrays to compare according to ``x < y`` (elementwise).
|
170
|
+
err_msg : str, optional
|
171
|
+
Error message to display on failure.
|
172
|
+
check_dtype, check_shape : bool, default: True
|
173
|
+
Whether to check agreement between actual and desired dtypes and shapes
|
174
|
+
check_scalar : bool, default: False
|
175
|
+
NumPy only: whether to check agreement between actual and desired types -
|
176
|
+
0d array vs scalar.
|
177
|
+
|
178
|
+
See Also
|
179
|
+
--------
|
180
|
+
xp_assert_close : Similar function for inexact equality checks.
|
181
|
+
numpy.testing.assert_array_equal : Similar function for NumPy arrays.
|
182
|
+
"""
|
183
|
+
xp = _check_ns_shape_dtype(x, y, check_dtype, check_shape, check_scalar)
|
184
|
+
x_np = as_numpy_array(x, xp=xp)
|
185
|
+
y_np = as_numpy_array(y, xp=xp)
|
186
|
+
np.testing.assert_array_less(x_np, y_np, err_msg=err_msg)
|
187
|
+
|
188
|
+
|
189
|
+
def xp_assert_close(
|
190
|
+
actual: Array,
|
191
|
+
desired: Array,
|
192
|
+
*,
|
193
|
+
rtol: float | None = None,
|
194
|
+
atol: float = 0,
|
195
|
+
err_msg: str = "",
|
196
|
+
check_dtype: bool = True,
|
197
|
+
check_shape: bool = True,
|
198
|
+
check_scalar: bool = False,
|
199
|
+
) -> None:
|
200
|
+
"""
|
201
|
+
Array-API compatible version of `np.testing.assert_allclose`.
|
202
|
+
|
203
|
+
Parameters
|
204
|
+
----------
|
205
|
+
actual : Array
|
206
|
+
The array produced by the tested function.
|
207
|
+
desired : Array
|
208
|
+
The expected array (typically hardcoded).
|
209
|
+
rtol : float, optional
|
210
|
+
Relative tolerance. Default: dtype-dependent.
|
211
|
+
atol : float, optional
|
212
|
+
Absolute tolerance. Default: 0.
|
213
|
+
err_msg : str, optional
|
214
|
+
Error message to display on failure.
|
215
|
+
check_dtype, check_shape : bool, default: True
|
216
|
+
Whether to check agreement between actual and desired dtypes and shapes
|
217
|
+
check_scalar : bool, default: False
|
218
|
+
NumPy only: whether to check agreement between actual and desired types -
|
219
|
+
0d array vs scalar.
|
220
|
+
|
221
|
+
See Also
|
222
|
+
--------
|
223
|
+
xp_assert_equal : Similar function for exact equality checks.
|
224
|
+
isclose : Public function for checking closeness.
|
225
|
+
numpy.testing.assert_allclose : Similar function for NumPy arrays.
|
226
|
+
|
227
|
+
Notes
|
228
|
+
-----
|
229
|
+
The default `atol` and `rtol` differ from `xp.all(xpx.isclose(a, b))`.
|
230
|
+
"""
|
231
|
+
xp = _check_ns_shape_dtype(actual, desired, check_dtype, check_shape, check_scalar)
|
232
|
+
|
233
|
+
if rtol is None:
|
234
|
+
if xp.isdtype(actual.dtype, ("real floating", "complex floating")):
|
235
|
+
# multiplier of 4 is used as for `np.float64` this puts the default `rtol`
|
236
|
+
# roughly half way between sqrt(eps) and the default for
|
237
|
+
# `numpy.testing.assert_allclose`, 1e-7
|
238
|
+
rtol = xp.finfo(actual.dtype).eps ** 0.5 * 4
|
239
|
+
else:
|
240
|
+
rtol = 1e-7
|
241
|
+
|
242
|
+
actual_np = as_numpy_array(actual, xp=xp)
|
243
|
+
desired_np = as_numpy_array(desired, xp=xp)
|
244
|
+
np.testing.assert_allclose( # pyright: ignore[reportCallIssue]
|
245
|
+
actual_np,
|
246
|
+
desired_np,
|
247
|
+
rtol=rtol, # pyright: ignore[reportArgumentType]
|
248
|
+
atol=atol,
|
249
|
+
err_msg=err_msg,
|
250
|
+
)
|
251
|
+
|
252
|
+
|
253
|
+
def xfail(
|
254
|
+
request: pytest.FixtureRequest, *, reason: str, strict: bool | None = None
|
255
|
+
) -> None:
|
256
|
+
"""
|
257
|
+
XFAIL the currently running test.
|
258
|
+
|
259
|
+
Unlike ``pytest.xfail``, allow rest of test to execute instead of immediately
|
260
|
+
halting it, so that it may result in a XPASS.
|
261
|
+
xref https://github.com/pandas-dev/pandas/issues/38902
|
262
|
+
|
263
|
+
Parameters
|
264
|
+
----------
|
265
|
+
request : pytest.FixtureRequest
|
266
|
+
``request`` argument of the test function.
|
267
|
+
reason : str
|
268
|
+
Reason for the expected failure.
|
269
|
+
strict: bool, optional
|
270
|
+
If True, the test will be marked as failed if it passes.
|
271
|
+
If False, the test will be marked as passed if it fails.
|
272
|
+
Default: ``xfail_strict`` value in ``pyproject.toml``, or False if absent.
|
273
|
+
"""
|
274
|
+
if strict is not None:
|
275
|
+
marker = pytest.mark.xfail(reason=reason, strict=strict)
|
276
|
+
else:
|
277
|
+
marker = pytest.mark.xfail(reason=reason)
|
278
|
+
request.node.add_marker(marker)
|
@@ -0,0 +1 @@
|
|
1
|
+
"""Modules housing private utility functions."""
|