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,463 @@
|
|
1
|
+
"""Update operations for read-only arrays."""
|
2
|
+
|
3
|
+
from __future__ import annotations
|
4
|
+
|
5
|
+
import operator
|
6
|
+
from collections.abc import Callable
|
7
|
+
from enum import Enum
|
8
|
+
from types import ModuleType
|
9
|
+
from typing import TYPE_CHECKING, ClassVar, cast
|
10
|
+
|
11
|
+
from ._utils import _compat
|
12
|
+
from ._utils._compat import (
|
13
|
+
array_namespace,
|
14
|
+
is_dask_array,
|
15
|
+
is_jax_array,
|
16
|
+
is_torch_array,
|
17
|
+
is_writeable_array,
|
18
|
+
)
|
19
|
+
from ._utils._helpers import meta_namespace
|
20
|
+
from ._utils._typing import Array, SetIndex
|
21
|
+
|
22
|
+
if TYPE_CHECKING: # pragma: no cover
|
23
|
+
# TODO import from typing (requires Python >=3.11)
|
24
|
+
from typing_extensions import Self
|
25
|
+
|
26
|
+
|
27
|
+
class _AtOp(Enum):
|
28
|
+
"""Operations for use in `xpx.at`."""
|
29
|
+
|
30
|
+
SET = "set"
|
31
|
+
ADD = "add"
|
32
|
+
SUBTRACT = "subtract"
|
33
|
+
MULTIPLY = "multiply"
|
34
|
+
DIVIDE = "divide"
|
35
|
+
POWER = "power"
|
36
|
+
MIN = "min"
|
37
|
+
MAX = "max"
|
38
|
+
|
39
|
+
# @override from Python 3.12
|
40
|
+
def __str__(self) -> str: # type: ignore[explicit-override] # pyright: ignore[reportImplicitOverride]
|
41
|
+
"""
|
42
|
+
Return string representation (useful for pytest logs).
|
43
|
+
|
44
|
+
Returns
|
45
|
+
-------
|
46
|
+
str
|
47
|
+
The operation's name.
|
48
|
+
"""
|
49
|
+
return self.value
|
50
|
+
|
51
|
+
|
52
|
+
class Undef(Enum):
|
53
|
+
"""Sentinel for undefined values."""
|
54
|
+
|
55
|
+
UNDEF = 0
|
56
|
+
|
57
|
+
|
58
|
+
_undef = Undef.UNDEF
|
59
|
+
|
60
|
+
|
61
|
+
class at: # pylint: disable=invalid-name # numpydoc ignore=PR02
|
62
|
+
"""
|
63
|
+
Update operations for read-only arrays.
|
64
|
+
|
65
|
+
This implements ``jax.numpy.ndarray.at`` for all writeable
|
66
|
+
backends (those that support ``__setitem__``) and routes
|
67
|
+
to the ``.at[]`` method for JAX arrays.
|
68
|
+
|
69
|
+
Parameters
|
70
|
+
----------
|
71
|
+
x : array
|
72
|
+
Input array.
|
73
|
+
idx : index, optional
|
74
|
+
Only `array API standard compliant indices
|
75
|
+
<https://data-apis.org/array-api/latest/API_specification/indexing.html>`_
|
76
|
+
are supported.
|
77
|
+
|
78
|
+
You may use two alternate syntaxes::
|
79
|
+
|
80
|
+
>>> import array_api_extra as xpx
|
81
|
+
>>> xpx.at(x, idx).set(value) # or add(value), etc.
|
82
|
+
>>> xpx.at(x)[idx].set(value)
|
83
|
+
|
84
|
+
copy : bool, optional
|
85
|
+
None (default)
|
86
|
+
The array parameter *may* be modified in place if it is
|
87
|
+
possible and beneficial for performance.
|
88
|
+
You should not reuse it after calling this function.
|
89
|
+
True
|
90
|
+
Ensure that the inputs are not modified.
|
91
|
+
False
|
92
|
+
Ensure that the update operation writes back to the input.
|
93
|
+
Raise ``ValueError`` if a copy cannot be avoided.
|
94
|
+
|
95
|
+
xp : array_namespace, optional
|
96
|
+
The standard-compatible namespace for `x`. Default: infer.
|
97
|
+
|
98
|
+
Returns
|
99
|
+
-------
|
100
|
+
Updated input array.
|
101
|
+
|
102
|
+
Warnings
|
103
|
+
--------
|
104
|
+
(a) When you omit the ``copy`` parameter, you should never reuse the parameter
|
105
|
+
array later on; ideally, you should reassign it immediately::
|
106
|
+
|
107
|
+
>>> import array_api_extra as xpx
|
108
|
+
>>> x = xpx.at(x, 0).set(2)
|
109
|
+
|
110
|
+
The above best practice pattern ensures that the behaviour won't change depending
|
111
|
+
on whether ``x`` is writeable or not, as the original ``x`` object is dereferenced
|
112
|
+
as soon as ``xpx.at`` returns; this way there is no risk to accidentally update it
|
113
|
+
twice.
|
114
|
+
|
115
|
+
On the reverse, the anti-pattern below must be avoided, as it will result in
|
116
|
+
different behaviour on read-only versus writeable arrays::
|
117
|
+
|
118
|
+
>>> x = xp.asarray([0, 0, 0])
|
119
|
+
>>> y = xpx.at(x, 0).set(2)
|
120
|
+
>>> z = xpx.at(x, 1).set(3)
|
121
|
+
|
122
|
+
In the above example, both calls to ``xpx.at`` update ``x`` in place *if possible*.
|
123
|
+
This causes the behaviour to diverge depending on whether ``x`` is writeable or not:
|
124
|
+
|
125
|
+
- If ``x`` is writeable, then after the snippet above you'll have
|
126
|
+
``x == y == z == [2, 3, 0]``
|
127
|
+
- If ``x`` is read-only, then you'll end up with
|
128
|
+
``x == [0, 0, 0]``, ``y == [2, 0, 0]`` and ``z == [0, 3, 0]``.
|
129
|
+
|
130
|
+
The correct pattern to use if you want diverging outputs from the same input is
|
131
|
+
to enforce copies::
|
132
|
+
|
133
|
+
>>> x = xp.asarray([0, 0, 0])
|
134
|
+
>>> y = xpx.at(x, 0).set(2, copy=True) # Never updates x
|
135
|
+
>>> z = xpx.at(x, 1).set(3) # May or may not update x in place
|
136
|
+
>>> del x # avoid accidental reuse of x as we don't know its state anymore
|
137
|
+
|
138
|
+
(b) The array API standard does not support integer array indices.
|
139
|
+
The behaviour of update methods when the index is an array of integers is
|
140
|
+
undefined and will vary between backends; this is particularly true when the
|
141
|
+
index contains multiple occurrences of the same index, e.g.::
|
142
|
+
|
143
|
+
>>> import numpy as np
|
144
|
+
>>> import jax.numpy as jnp
|
145
|
+
>>> import array_api_extra as xpx
|
146
|
+
>>> xpx.at(np.asarray([123]), np.asarray([0, 0])).add(1)
|
147
|
+
array([124])
|
148
|
+
>>> xpx.at(jnp.asarray([123]), jnp.asarray([0, 0])).add(1)
|
149
|
+
Array([125], dtype=int32)
|
150
|
+
|
151
|
+
See Also
|
152
|
+
--------
|
153
|
+
jax.numpy.ndarray.at : Equivalent array method in JAX.
|
154
|
+
|
155
|
+
Notes
|
156
|
+
-----
|
157
|
+
`sparse <https://sparse.pydata.org/>`_, as well as read-only arrays from libraries
|
158
|
+
not explicitly covered by ``array-api-compat``, are not supported by update
|
159
|
+
methods.
|
160
|
+
|
161
|
+
Boolean masks are supported on Dask and jitted JAX arrays exclusively
|
162
|
+
when `idx` has the same shape as `x` and `y` is 0-dimensional.
|
163
|
+
Note that this support is not available in JAX's native
|
164
|
+
``x.at[mask].set(y)``.
|
165
|
+
|
166
|
+
This pattern::
|
167
|
+
|
168
|
+
>>> mask = m(x)
|
169
|
+
>>> x[mask] = f(x[mask])
|
170
|
+
|
171
|
+
Can't be replaced by `at`, as it won't work on Dask and JAX inside jax.jit::
|
172
|
+
|
173
|
+
>>> mask = m(x)
|
174
|
+
>>> x = xpx.at(x, mask).set(f(x[mask]) # Crash on Dask and jax.jit
|
175
|
+
|
176
|
+
You should instead use::
|
177
|
+
|
178
|
+
>>> x = xp.where(m(x), f(x), x)
|
179
|
+
|
180
|
+
Examples
|
181
|
+
--------
|
182
|
+
Given either of these equivalent expressions::
|
183
|
+
|
184
|
+
>>> import array_api_extra as xpx
|
185
|
+
>>> x = xpx.at(x)[1].add(2)
|
186
|
+
>>> x = xpx.at(x, 1).add(2)
|
187
|
+
|
188
|
+
If x is a JAX array, they are the same as::
|
189
|
+
|
190
|
+
>>> x = x.at[1].add(2)
|
191
|
+
|
192
|
+
If x is a read-only NumPy array, they are the same as::
|
193
|
+
|
194
|
+
>>> x = x.copy()
|
195
|
+
>>> x[1] += 2
|
196
|
+
|
197
|
+
For other known backends, they are the same as::
|
198
|
+
|
199
|
+
>>> x[1] += 2
|
200
|
+
"""
|
201
|
+
|
202
|
+
_x: Array
|
203
|
+
_idx: SetIndex | Undef
|
204
|
+
__slots__: ClassVar[tuple[str, ...]] = ("_idx", "_x")
|
205
|
+
|
206
|
+
def __init__(
|
207
|
+
self, x: Array, idx: SetIndex | Undef = _undef, /
|
208
|
+
) -> None: # numpydoc ignore=GL08
|
209
|
+
self._x = x
|
210
|
+
self._idx = idx
|
211
|
+
|
212
|
+
def __getitem__(self, idx: SetIndex, /) -> Self: # numpydoc ignore=PR01,RT01
|
213
|
+
"""
|
214
|
+
Allow for the alternate syntax ``at(x)[start:stop:step]``.
|
215
|
+
|
216
|
+
It looks prettier than ``at(x, slice(start, stop, step))``
|
217
|
+
and feels more intuitive coming from the JAX documentation.
|
218
|
+
"""
|
219
|
+
if self._idx is not _undef:
|
220
|
+
msg = "Index has already been set"
|
221
|
+
raise ValueError(msg)
|
222
|
+
return type(self)(self._x, idx)
|
223
|
+
|
224
|
+
def _op(
|
225
|
+
self,
|
226
|
+
at_op: _AtOp,
|
227
|
+
in_place_op: Callable[[Array, Array | complex], Array] | None,
|
228
|
+
out_of_place_op: Callable[[Array, Array], Array] | None,
|
229
|
+
y: Array | complex,
|
230
|
+
/,
|
231
|
+
copy: bool | None,
|
232
|
+
xp: ModuleType | None,
|
233
|
+
) -> Array:
|
234
|
+
"""
|
235
|
+
Implement all update operations.
|
236
|
+
|
237
|
+
Parameters
|
238
|
+
----------
|
239
|
+
at_op : _AtOp
|
240
|
+
Method of JAX's Array.at[].
|
241
|
+
in_place_op : Callable[[Array, Array | complex], Array] | None
|
242
|
+
In-place operation to apply on mutable backends::
|
243
|
+
|
244
|
+
x[idx] = in_place_op(x[idx], y)
|
245
|
+
|
246
|
+
If None::
|
247
|
+
|
248
|
+
x[idx] = y
|
249
|
+
|
250
|
+
out_of_place_op : Callable[[Array, Array], Array] | None
|
251
|
+
Out-of-place operation to apply when idx is a boolean mask and the backend
|
252
|
+
doesn't support in-place updates::
|
253
|
+
|
254
|
+
x = xp.where(idx, out_of_place_op(x, y), x)
|
255
|
+
|
256
|
+
If None::
|
257
|
+
|
258
|
+
x = xp.where(idx, y, x)
|
259
|
+
|
260
|
+
y : array or complex
|
261
|
+
Right-hand side of the operation.
|
262
|
+
copy : bool or None
|
263
|
+
Whether to copy the input array. See the class docstring for details.
|
264
|
+
xp : array_namespace, optional
|
265
|
+
The array namespace for the input array. Default: infer.
|
266
|
+
|
267
|
+
Returns
|
268
|
+
-------
|
269
|
+
Array
|
270
|
+
Updated `x`.
|
271
|
+
"""
|
272
|
+
from ._funcs import apply_where # pylint: disable=cyclic-import
|
273
|
+
|
274
|
+
x, idx = self._x, self._idx
|
275
|
+
xp = array_namespace(x, y) if xp is None else xp
|
276
|
+
|
277
|
+
if isinstance(idx, Undef):
|
278
|
+
msg = (
|
279
|
+
"Index has not been set.\n"
|
280
|
+
"Usage: either\n"
|
281
|
+
" at(x, idx).set(value)\n"
|
282
|
+
"or\n"
|
283
|
+
" at(x)[idx].set(value)\n"
|
284
|
+
"(same for all other methods)."
|
285
|
+
)
|
286
|
+
raise ValueError(msg)
|
287
|
+
|
288
|
+
if copy not in (True, False, None):
|
289
|
+
msg = f"copy must be True, False, or None; got {copy!r}"
|
290
|
+
raise ValueError(msg)
|
291
|
+
|
292
|
+
writeable = None if copy else is_writeable_array(x)
|
293
|
+
|
294
|
+
# JAX inside jax.jit doesn't support in-place updates with boolean
|
295
|
+
# masks; Dask exclusively supports __setitem__ but not iops.
|
296
|
+
# We can handle the common special case of 0-dimensional y
|
297
|
+
# with where(idx, y, x) instead.
|
298
|
+
if (
|
299
|
+
(is_dask_array(idx) or is_jax_array(idx))
|
300
|
+
and idx.dtype == xp.bool
|
301
|
+
and idx.shape == x.shape
|
302
|
+
):
|
303
|
+
y_xp = xp.asarray(y, dtype=x.dtype, device=_compat.device(x))
|
304
|
+
if y_xp.ndim == 0:
|
305
|
+
if out_of_place_op: # add(), subtract(), ...
|
306
|
+
# suppress inf warnings on Dask
|
307
|
+
out = apply_where(
|
308
|
+
idx, (x, y_xp), out_of_place_op, fill_value=x, xp=xp
|
309
|
+
)
|
310
|
+
# Undo int->float promotion on JAX after _AtOp.DIVIDE
|
311
|
+
out = xp.astype(out, x.dtype, copy=False)
|
312
|
+
else: # set()
|
313
|
+
out = xp.where(idx, y_xp, x)
|
314
|
+
|
315
|
+
if copy is False:
|
316
|
+
x[()] = out
|
317
|
+
return x
|
318
|
+
return out
|
319
|
+
|
320
|
+
# else: this will work on eager JAX and crash on jax.jit and Dask
|
321
|
+
|
322
|
+
if copy or (copy is None and not writeable):
|
323
|
+
if is_jax_array(x):
|
324
|
+
# Use JAX's at[]
|
325
|
+
func = cast(
|
326
|
+
Callable[[Array | complex], Array],
|
327
|
+
getattr(x.at[idx], at_op.value), # type: ignore[attr-defined] # pyright: ignore[reportAttributeAccessIssue,reportUnknownArgumentType]
|
328
|
+
)
|
329
|
+
out = func(y)
|
330
|
+
# Undo int->float promotion on JAX after _AtOp.DIVIDE
|
331
|
+
return xp.astype(out, x.dtype, copy=False)
|
332
|
+
|
333
|
+
# Emulate at[] behaviour for non-JAX arrays
|
334
|
+
# with a copy followed by an update
|
335
|
+
|
336
|
+
x = xp.asarray(x, copy=True)
|
337
|
+
# A copy of a read-only numpy array is writeable
|
338
|
+
# Note: this assumes that a copy of a writeable array is writeable
|
339
|
+
assert not writeable
|
340
|
+
writeable = None
|
341
|
+
|
342
|
+
if writeable is None:
|
343
|
+
writeable = is_writeable_array(x)
|
344
|
+
if not writeable:
|
345
|
+
# sparse crashes here
|
346
|
+
msg = f"Can't update read-only array {x}"
|
347
|
+
raise ValueError(msg)
|
348
|
+
|
349
|
+
# Work around bug in PyTorch where __setitem__ doesn't
|
350
|
+
# always support mismatched dtypes
|
351
|
+
# https://github.com/pytorch/pytorch/issues/150017
|
352
|
+
if is_torch_array(y):
|
353
|
+
y = xp.astype(y, x.dtype, copy=False)
|
354
|
+
|
355
|
+
# Backends without boolean indexing (other than JAX) crash here
|
356
|
+
if in_place_op: # add(), subtract(), ...
|
357
|
+
x[idx] = in_place_op(x[idx], y)
|
358
|
+
else: # set()
|
359
|
+
x[idx] = y
|
360
|
+
return x
|
361
|
+
|
362
|
+
def set(
|
363
|
+
self,
|
364
|
+
y: Array | complex,
|
365
|
+
/,
|
366
|
+
copy: bool | None = None,
|
367
|
+
xp: ModuleType | None = None,
|
368
|
+
) -> Array: # numpydoc ignore=PR01,RT01
|
369
|
+
"""Apply ``x[idx] = y`` and return the update array."""
|
370
|
+
return self._op(_AtOp.SET, None, None, y, copy=copy, xp=xp)
|
371
|
+
|
372
|
+
def add(
|
373
|
+
self,
|
374
|
+
y: Array | complex,
|
375
|
+
/,
|
376
|
+
copy: bool | None = None,
|
377
|
+
xp: ModuleType | None = None,
|
378
|
+
) -> Array: # numpydoc ignore=PR01,RT01
|
379
|
+
"""Apply ``x[idx] += y`` and return the updated array."""
|
380
|
+
|
381
|
+
# Note for this and all other methods based on _iop:
|
382
|
+
# operator.iadd and operator.add subtly differ in behaviour, as
|
383
|
+
# only iadd will trigger exceptions when y has an incompatible dtype.
|
384
|
+
return self._op(_AtOp.ADD, operator.iadd, operator.add, y, copy=copy, xp=xp)
|
385
|
+
|
386
|
+
def subtract(
|
387
|
+
self,
|
388
|
+
y: Array | complex,
|
389
|
+
/,
|
390
|
+
copy: bool | None = None,
|
391
|
+
xp: ModuleType | None = None,
|
392
|
+
) -> Array: # numpydoc ignore=PR01,RT01
|
393
|
+
"""Apply ``x[idx] -= y`` and return the updated array."""
|
394
|
+
return self._op(
|
395
|
+
_AtOp.SUBTRACT, operator.isub, operator.sub, y, copy=copy, xp=xp
|
396
|
+
)
|
397
|
+
|
398
|
+
def multiply(
|
399
|
+
self,
|
400
|
+
y: Array | complex,
|
401
|
+
/,
|
402
|
+
copy: bool | None = None,
|
403
|
+
xp: ModuleType | None = None,
|
404
|
+
) -> Array: # numpydoc ignore=PR01,RT01
|
405
|
+
"""Apply ``x[idx] *= y`` and return the updated array."""
|
406
|
+
return self._op(
|
407
|
+
_AtOp.MULTIPLY, operator.imul, operator.mul, y, copy=copy, xp=xp
|
408
|
+
)
|
409
|
+
|
410
|
+
def divide(
|
411
|
+
self,
|
412
|
+
y: Array | complex,
|
413
|
+
/,
|
414
|
+
copy: bool | None = None,
|
415
|
+
xp: ModuleType | None = None,
|
416
|
+
) -> Array: # numpydoc ignore=PR01,RT01
|
417
|
+
"""Apply ``x[idx] /= y`` and return the updated array."""
|
418
|
+
return self._op(
|
419
|
+
_AtOp.DIVIDE, operator.itruediv, operator.truediv, y, copy=copy, xp=xp
|
420
|
+
)
|
421
|
+
|
422
|
+
def power(
|
423
|
+
self,
|
424
|
+
y: Array | complex,
|
425
|
+
/,
|
426
|
+
copy: bool | None = None,
|
427
|
+
xp: ModuleType | None = None,
|
428
|
+
) -> Array: # numpydoc ignore=PR01,RT01
|
429
|
+
"""Apply ``x[idx] **= y`` and return the updated array."""
|
430
|
+
return self._op(_AtOp.POWER, operator.ipow, operator.pow, y, copy=copy, xp=xp)
|
431
|
+
|
432
|
+
def min(
|
433
|
+
self,
|
434
|
+
y: Array | complex,
|
435
|
+
/,
|
436
|
+
copy: bool | None = None,
|
437
|
+
xp: ModuleType | None = None,
|
438
|
+
) -> Array: # numpydoc ignore=PR01,RT01
|
439
|
+
"""Apply ``x[idx] = minimum(x[idx], y)`` and return the updated array."""
|
440
|
+
# On Dask, this function runs on the chunks, so we need to determine the
|
441
|
+
# namespace that Dask is wrapping.
|
442
|
+
# Note that da.minimum _incidentally_ works on NumPy, CuPy, and sparse
|
443
|
+
# thanks to all these meta-namespaces implementing the __array_ufunc__
|
444
|
+
# interface, but there's no guarantee that it will work for other
|
445
|
+
# wrapped libraries in the future.
|
446
|
+
xp = array_namespace(self._x) if xp is None else xp
|
447
|
+
mxp = meta_namespace(self._x, xp=xp)
|
448
|
+
y = xp.asarray(y)
|
449
|
+
return self._op(_AtOp.MIN, mxp.minimum, mxp.minimum, y, copy=copy, xp=xp)
|
450
|
+
|
451
|
+
def max(
|
452
|
+
self,
|
453
|
+
y: Array | complex,
|
454
|
+
/,
|
455
|
+
copy: bool | None = None,
|
456
|
+
xp: ModuleType | None = None,
|
457
|
+
) -> Array: # numpydoc ignore=PR01,RT01
|
458
|
+
"""Apply ``x[idx] = maximum(x[idx], y)`` and return the updated array."""
|
459
|
+
# See note on min()
|
460
|
+
xp = array_namespace(self._x) if xp is None else xp
|
461
|
+
mxp = meta_namespace(self._x, xp=xp)
|
462
|
+
y = xp.asarray(y)
|
463
|
+
return self._op(_AtOp.MAX, mxp.maximum, mxp.maximum, y, copy=copy, xp=xp)
|
@@ -0,0 +1,46 @@
|
|
1
|
+
"""Backends against which array-api-extra runs its tests."""
|
2
|
+
|
3
|
+
from __future__ import annotations
|
4
|
+
|
5
|
+
from enum import Enum
|
6
|
+
|
7
|
+
__all__ = ["Backend"]
|
8
|
+
|
9
|
+
|
10
|
+
class Backend(Enum): # numpydoc ignore=PR02
|
11
|
+
"""
|
12
|
+
All array library backends explicitly tested by array-api-extra.
|
13
|
+
|
14
|
+
Parameters
|
15
|
+
----------
|
16
|
+
value : str
|
17
|
+
Tag of the backend's module, in the format ``<namespace>[:<extra tag>]``.
|
18
|
+
"""
|
19
|
+
|
20
|
+
# Use :<tag> to prevent Enum from deduplicating items with the same value
|
21
|
+
ARRAY_API_STRICT = "array_api_strict"
|
22
|
+
ARRAY_API_STRICTEST = "array_api_strict:strictest"
|
23
|
+
NUMPY = "numpy"
|
24
|
+
NUMPY_READONLY = "numpy:readonly"
|
25
|
+
CUPY = "cupy"
|
26
|
+
TORCH = "torch"
|
27
|
+
TORCH_GPU = "torch:gpu"
|
28
|
+
DASK = "dask.array"
|
29
|
+
SPARSE = "sparse"
|
30
|
+
JAX = "jax.numpy"
|
31
|
+
JAX_GPU = "jax.numpy:gpu"
|
32
|
+
|
33
|
+
def __str__(self) -> str: # type: ignore[explicit-override] # pyright: ignore[reportImplicitOverride] # numpydoc ignore=RT01
|
34
|
+
"""Pretty-print parameterized test names."""
|
35
|
+
return (
|
36
|
+
self.name.lower().replace("_gpu", ":gpu").replace("_readonly", ":readonly")
|
37
|
+
)
|
38
|
+
|
39
|
+
@property
|
40
|
+
def modname(self) -> str: # numpydoc ignore=RT01
|
41
|
+
"""Module name to be imported."""
|
42
|
+
return self.value.split(":")[0]
|
43
|
+
|
44
|
+
def like(self, *others: Backend) -> bool: # numpydoc ignore=PR01,RT01
|
45
|
+
"""Check if this backend uses the same module as others."""
|
46
|
+
return any(self.modname == other.modname for other in others)
|