scipy 1.15.3__cp313-cp313t-macosx_14_0_arm64.whl → 1.16.0rc2__cp313-cp313t-macosx_14_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/__config__.py +3 -3
- scipy/__init__.py +3 -6
- scipy/_cyutility.cpython-313t-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-313t-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-313t-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-313t-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-313t-darwin.so +0 -0
- scipy/cluster/_optimal_leaf_ordering.cpython-313t-darwin.so +0 -0
- scipy/cluster/_vq.cpython-313t-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-313t-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-313t-darwin.so +0 -0
- scipy/integrate/_lsoda.cpython-313t-darwin.so +0 -0
- scipy/integrate/_ode.py +9 -2
- scipy/integrate/_odepack.cpython-313t-darwin.so +0 -0
- scipy/integrate/_quad_vec.py +21 -29
- scipy/integrate/_quadpack.cpython-313t-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-313t-darwin.so +0 -0
- scipy/integrate/_vode.cpython-313t-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-313t-darwin.so +0 -0
- scipy/interpolate/_dierckx.cpython-313t-darwin.so +0 -0
- scipy/interpolate/_fitpack.cpython-313t-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-313t-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-313t-darwin.so +0 -0
- scipy/interpolate/_rbf.py +2 -2
- scipy/interpolate/_rbfinterp.py +1 -1
- scipy/interpolate/_rbfinterp_pythran.cpython-313t-darwin.so +0 -0
- scipy/interpolate/_rgi.py +31 -26
- scipy/interpolate/_rgi_cython.cpython-313t-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-313t-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-313t-darwin.so +0 -0
- scipy/io/matlab/_mio_utils.cpython-313t-darwin.so +0 -0
- scipy/io/matlab/_miobase.py +4 -1
- scipy/io/matlab/_streams.cpython-313t-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-313t-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-313t-darwin.so +0 -0
- scipy/linalg/_decomp_ldl.py +4 -1
- scipy/linalg/_decomp_lu.py +18 -6
- scipy/linalg/_decomp_lu_cython.cpython-313t-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-313t-darwin.so +0 -0
- scipy/linalg/_expm_frechet.py +4 -0
- scipy/linalg/_fblas.cpython-313t-darwin.so +0 -0
- scipy/linalg/_flapack.cpython-313t-darwin.so +0 -0
- scipy/linalg/_linalg_pythran.cpython-313t-darwin.so +0 -0
- scipy/linalg/_matfuncs.py +187 -4
- scipy/linalg/_matfuncs_expm.cpython-313t-darwin.so +0 -0
- scipy/linalg/_matfuncs_schur_sqrtm.cpython-313t-darwin.so +0 -0
- scipy/linalg/_matfuncs_sqrtm.py +1 -99
- scipy/linalg/_matfuncs_sqrtm_triu.cpython-313t-darwin.so +0 -0
- scipy/linalg/_procrustes.py +2 -0
- scipy/linalg/_sketches.py +17 -6
- scipy/linalg/_solve_toeplitz.cpython-313t-darwin.so +0 -0
- scipy/linalg/_solvers.py +7 -2
- scipy/linalg/_special_matrices.py +26 -36
- scipy/linalg/cython_blas.cpython-313t-darwin.so +0 -0
- scipy/linalg/cython_lapack.cpython-313t-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-313t-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-313t-darwin.so +0 -0
- scipy/ndimage/_ni_docstrings.py +5 -1
- scipy/ndimage/_ni_label.cpython-313t-darwin.so +0 -0
- scipy/ndimage/_ni_support.py +1 -5
- scipy/ndimage/_rank_filter_1d.cpython-313t-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-313t-darwin.so +0 -0
- scipy/optimize/_basinhopping.py +13 -7
- scipy/optimize/_bglu_dense.cpython-313t-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-313t-darwin.so +0 -0
- scipy/optimize/_dual_annealing.py +1 -1
- scipy/optimize/_elementwise.py +1 -4
- scipy/optimize/_group_columns.cpython-313t-darwin.so +0 -0
- scipy/optimize/_lbfgsb.cpython-313t-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-313t-darwin.so +0 -0
- scipy/optimize/_lsq/common.py +3 -3
- scipy/optimize/_lsq/dogbox.py +16 -2
- scipy/optimize/_lsq/givens_elimination.cpython-313t-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-313t-darwin.so +0 -0
- scipy/optimize/_minpack_py.py +21 -14
- scipy/optimize/_moduleTNC.cpython-313t-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-313t-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-313t-darwin.so +0 -0
- scipy/optimize/_spectral.py +1 -1
- scipy/optimize/_tnc.py +8 -1
- scipy/optimize/_trlib/_trlib.cpython-313t-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-313t-darwin.so +0 -0
- scipy/optimize/_zeros_py.py +97 -17
- scipy/optimize/cython_optimize/_zeros.cpython-313t-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-313t-darwin.so +0 -0
- scipy/signal/_peak_finding_utils.cpython-313t-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-313t-darwin.so +0 -0
- scipy/signal/_sosfilt.cpython-313t-darwin.so +0 -0
- scipy/signal/_spectral_py.py +230 -50
- scipy/signal/_spline.cpython-313t-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-313t-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-313t-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-313t-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-313t-darwin.so +0 -0
- scipy/sparse/csgraph/_matching.cpython-313t-darwin.so +0 -0
- scipy/sparse/csgraph/_min_spanning_tree.cpython-313t-darwin.so +0 -0
- scipy/sparse/csgraph/_reordering.cpython-313t-darwin.so +0 -0
- scipy/sparse/csgraph/_shortest_path.cpython-313t-darwin.so +0 -0
- scipy/sparse/csgraph/_tools.cpython-313t-darwin.so +0 -0
- scipy/sparse/csgraph/_traversal.cpython-313t-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-313t-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-313t-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-313t-darwin.so +0 -0
- scipy/sparse/linalg/_propack/_dpropack.cpython-313t-darwin.so +0 -0
- scipy/sparse/linalg/_propack/_spropack.cpython-313t-darwin.so +0 -0
- scipy/sparse/linalg/_propack/_zpropack.cpython-313t-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-313t-darwin.so +0 -0
- scipy/spatial/_distance_pybind.cpython-313t-darwin.so +0 -0
- scipy/spatial/_distance_wrap.cpython-313t-darwin.so +0 -0
- scipy/spatial/_hausdorff.cpython-313t-darwin.so +0 -0
- scipy/spatial/_qhull.cpython-313t-darwin.so +0 -0
- scipy/spatial/_voronoi.cpython-313t-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-313t-darwin.so +0 -0
- scipy/spatial/transform/_rotation.cpython-313t-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-313t-darwin.so +0 -0
- scipy/special/_ellip_harm_2.cpython-313t-darwin.so +0 -0
- scipy/special/_gufuncs.cpython-313t-darwin.so +0 -0
- scipy/special/_logsumexp.py +67 -58
- scipy/special/_orthogonal.pyi +1 -1
- scipy/special/_specfun.cpython-313t-darwin.so +0 -0
- scipy/special/_special_ufuncs.cpython-313t-darwin.so +0 -0
- scipy/special/_spherical_bessel.py +4 -4
- scipy/special/_support_alternative_backends.py +212 -119
- scipy/special/_test_internal.cpython-313t-darwin.so +0 -0
- scipy/special/_testutils.py +4 -4
- scipy/special/_ufuncs.cpython-313t-darwin.so +0 -0
- scipy/special/_ufuncs.pyi +1 -0
- scipy/special/_ufuncs.pyx +215 -1400
- scipy/special/_ufuncs_cxx.cpython-313t-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-313t-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-313t-darwin.so +0 -0
- scipy/stats/_axis_nan_policy.py +5 -12
- scipy/stats/_biasedurn.cpython-313t-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-313t-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-313t-darwin.so +0 -0
- scipy/stats/_qmvnt.py +16 -95
- scipy/stats/_qmvnt_cy.cpython-313t-darwin.so +0 -0
- scipy/stats/_quantile.py +335 -0
- scipy/stats/_rcont/rcont.cpython-313t-darwin.so +0 -0
- scipy/stats/_resampling.py +4 -29
- scipy/stats/_sampling.py +1 -1
- scipy/stats/_sobol.cpython-313t-darwin.so +0 -0
- scipy/stats/_stats.cpython-313t-darwin.so +0 -0
- scipy/stats/_stats_mstats_common.py +21 -2
- scipy/stats/_stats_py.py +550 -476
- scipy/stats/_stats_pythran.cpython-313t-darwin.so +0 -0
- scipy/stats/_unuran/unuran_wrapper.cpython-313t-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 +559 -566
- 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-313t-darwin.so +0 -0
- scipy/optimize/_cobyla.cpython-313t-darwin.so +0 -0
- scipy/optimize/_cython_nnls.cpython-313t-darwin.so +0 -0
- scipy/optimize/_slsqp.cpython-313t-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-313t-darwin.so +0 -0
- scipy-1.15.3.dist-info/WHEEL +0 -4
scipy/conftest.py
CHANGED
@@ -4,6 +4,7 @@ import os
|
|
4
4
|
import warnings
|
5
5
|
import tempfile
|
6
6
|
from contextlib import contextmanager
|
7
|
+
from typing import Literal
|
7
8
|
|
8
9
|
import numpy as np
|
9
10
|
import numpy.testing as npt
|
@@ -11,8 +12,12 @@ import pytest
|
|
11
12
|
import hypothesis
|
12
13
|
|
13
14
|
from scipy._lib._fpumode import get_fpu_mode
|
15
|
+
from scipy._lib._array_api import (
|
16
|
+
SCIPY_ARRAY_API, SCIPY_DEVICE, array_namespace, default_xp,
|
17
|
+
is_cupy, is_dask, is_jax,
|
18
|
+
)
|
14
19
|
from scipy._lib._testutils import FPUModeChangeWarning
|
15
|
-
from scipy._lib.
|
20
|
+
from scipy._lib.array_api_extra.testing import patch_lazy_xp_functions
|
16
21
|
from scipy._lib import _pep440
|
17
22
|
|
18
23
|
try:
|
@@ -29,12 +34,6 @@ except Exception:
|
|
29
34
|
|
30
35
|
|
31
36
|
def pytest_configure(config):
|
32
|
-
config.addinivalue_line("markers",
|
33
|
-
"slow: Tests that are very slow.")
|
34
|
-
config.addinivalue_line("markers",
|
35
|
-
"xslow: mark test as extremely slow (not run unless explicitly requested)")
|
36
|
-
config.addinivalue_line("markers",
|
37
|
-
"xfail_on_32bit: mark test as failing on 32-bit platforms")
|
38
37
|
try:
|
39
38
|
import pytest_timeout # noqa:F401
|
40
39
|
except Exception:
|
@@ -47,14 +46,7 @@ def pytest_configure(config):
|
|
47
46
|
except Exception:
|
48
47
|
config.addinivalue_line(
|
49
48
|
"markers", 'fail_slow: mark a test for a non-default timeout failure')
|
50
|
-
|
51
|
-
"skip_xp_backends(backends, reason=None, np_only=False, cpu_only=False, "
|
52
|
-
"exceptions=None): "
|
53
|
-
"mark the desired skip configuration for the `skip_xp_backends` fixture.")
|
54
|
-
config.addinivalue_line("markers",
|
55
|
-
"xfail_xp_backends(backends, reason=None, np_only=False, cpu_only=False, "
|
56
|
-
"exceptions=None): "
|
57
|
-
"mark the desired xfail configuration for the `xfail_xp_backends` fixture.")
|
49
|
+
|
58
50
|
if not PARALLEL_RUN_AVAILABLE:
|
59
51
|
config.addinivalue_line(
|
60
52
|
'markers',
|
@@ -141,17 +133,21 @@ if not PARALLEL_RUN_AVAILABLE:
|
|
141
133
|
|
142
134
|
|
143
135
|
# Array API backend handling
|
136
|
+
xp_known_backends = {'numpy', 'array_api_strict', 'torch', 'cupy', 'jax.numpy',
|
137
|
+
'dask.array'}
|
144
138
|
xp_available_backends = {'numpy': np}
|
139
|
+
xp_skip_cpu_only_backends = set()
|
140
|
+
xp_skip_eager_only_backends = set()
|
145
141
|
|
146
|
-
if SCIPY_ARRAY_API
|
142
|
+
if SCIPY_ARRAY_API:
|
147
143
|
# fill the dict of backends with available libraries
|
148
144
|
try:
|
149
145
|
import array_api_strict
|
150
146
|
xp_available_backends.update({'array_api_strict': array_api_strict})
|
151
|
-
if _pep440.parse(array_api_strict.__version__) < _pep440.Version('2.
|
152
|
-
raise ImportError("array-api-strict must be >= version 2.
|
147
|
+
if _pep440.parse(array_api_strict.__version__) < _pep440.Version('2.3'):
|
148
|
+
raise ImportError("array-api-strict must be >= version 2.3")
|
153
149
|
array_api_strict.set_array_api_strict_flags(
|
154
|
-
api_version='
|
150
|
+
api_version='2024.12'
|
155
151
|
)
|
156
152
|
except ImportError:
|
157
153
|
pass
|
@@ -159,14 +155,35 @@ if SCIPY_ARRAY_API and isinstance(SCIPY_ARRAY_API, str):
|
|
159
155
|
try:
|
160
156
|
import torch # type: ignore[import-not-found]
|
161
157
|
xp_available_backends.update({'torch': torch})
|
162
|
-
# can use `mps` or `cpu`
|
163
158
|
torch.set_default_device(SCIPY_DEVICE)
|
159
|
+
if SCIPY_DEVICE != "cpu":
|
160
|
+
xp_skip_cpu_only_backends.add('torch')
|
161
|
+
|
162
|
+
# default to float64 unless explicitly requested
|
163
|
+
default = os.getenv('SCIPY_DEFAULT_DTYPE', default='float64')
|
164
|
+
if default == 'float64':
|
165
|
+
torch.set_default_dtype(torch.float64)
|
166
|
+
elif default != "float32":
|
167
|
+
raise ValueError(
|
168
|
+
"SCIPY_DEFAULT_DTYPE env var, if set, can only be either 'float64' "
|
169
|
+
f"or 'float32'. Got '{default}' instead."
|
170
|
+
)
|
164
171
|
except ImportError:
|
165
172
|
pass
|
166
173
|
|
167
174
|
try:
|
168
175
|
import cupy # type: ignore[import-not-found]
|
176
|
+
# Note: cupy disregards SCIPY_DEVICE and always runs on cuda.
|
177
|
+
# It will fail to import if you don't have CUDA hardware and drivers.
|
169
178
|
xp_available_backends.update({'cupy': cupy})
|
179
|
+
xp_skip_cpu_only_backends.add('cupy')
|
180
|
+
|
181
|
+
# this is annoying in CuPy 13.x
|
182
|
+
warnings.filterwarnings(
|
183
|
+
'ignore', 'cupyx.jit.rawkernel is experimental', category=FutureWarning
|
184
|
+
)
|
185
|
+
from cupyx.scipy import signal
|
186
|
+
del signal
|
170
187
|
except ImportError:
|
171
188
|
pass
|
172
189
|
|
@@ -175,16 +192,35 @@ if SCIPY_ARRAY_API and isinstance(SCIPY_ARRAY_API, str):
|
|
175
192
|
xp_available_backends.update({'jax.numpy': jax.numpy})
|
176
193
|
jax.config.update("jax_enable_x64", True)
|
177
194
|
jax.config.update("jax_default_device", jax.devices(SCIPY_DEVICE)[0])
|
195
|
+
if SCIPY_DEVICE != "cpu":
|
196
|
+
xp_skip_cpu_only_backends.add('jax.numpy')
|
197
|
+
# JAX can be eager or lazy (when wrapped in jax.jit). However it is
|
198
|
+
# recommended by upstream devs to assume it's always lazy.
|
199
|
+
xp_skip_eager_only_backends.add('jax.numpy')
|
200
|
+
except ImportError:
|
201
|
+
pass
|
202
|
+
|
203
|
+
try:
|
204
|
+
import dask.array as da
|
205
|
+
xp_available_backends.update({'dask.array': da})
|
206
|
+
# Dask can wrap around cupy. However, this is untested in scipy
|
207
|
+
# (and will almost surely not work as delegation will misbehave).
|
208
|
+
|
209
|
+
# Dask, strictly speaking, can be eager, in the sense that
|
210
|
+
# __array__, __bool__ etc. are implemented and do not raise.
|
211
|
+
# However, calling them triggers an extra computation of the whole graph
|
212
|
+
# until that point, which is highly destructive for performance.
|
213
|
+
xp_skip_eager_only_backends.add('dask.array')
|
178
214
|
except ImportError:
|
179
215
|
pass
|
180
216
|
|
181
217
|
# by default, use all available backends
|
182
|
-
if
|
218
|
+
if (
|
219
|
+
isinstance(SCIPY_ARRAY_API, str)
|
220
|
+
and SCIPY_ARRAY_API.lower() not in ("1", "true", "all")
|
221
|
+
):
|
183
222
|
SCIPY_ARRAY_API_ = json.loads(SCIPY_ARRAY_API)
|
184
|
-
|
185
|
-
if 'all' in SCIPY_ARRAY_API_:
|
186
|
-
pass # same as True
|
187
|
-
else:
|
223
|
+
if SCIPY_ARRAY_API_ != ['all']:
|
188
224
|
# only select a subset of backend by filtering out the dict
|
189
225
|
try:
|
190
226
|
xp_available_backends = {
|
@@ -192,166 +228,220 @@ if SCIPY_ARRAY_API and isinstance(SCIPY_ARRAY_API, str):
|
|
192
228
|
for backend in SCIPY_ARRAY_API_
|
193
229
|
}
|
194
230
|
except KeyError:
|
195
|
-
msg =
|
231
|
+
msg = ("'--array-api-backend' must be in "
|
232
|
+
f"{list(xp_available_backends)}; got {SCIPY_ARRAY_API_}")
|
196
233
|
raise ValueError(msg)
|
197
234
|
|
198
|
-
|
199
|
-
|
235
|
+
assert not set(xp_available_backends) - xp_known_backends
|
236
|
+
xp_skip_np_only_backends = set(xp_available_backends) - {"numpy"}
|
200
237
|
|
201
|
-
array_api_compatible = pytest.mark.parametrize("xp", xp_available_backends.values())
|
202
238
|
|
203
|
-
|
204
|
-
|
205
|
-
|
239
|
+
@pytest.fixture(params=[
|
240
|
+
pytest.param(v, id=k, marks=pytest.mark.array_api_backends)
|
241
|
+
for k, v in xp_available_backends.items()
|
242
|
+
])
|
243
|
+
def xp(request, monkeypatch):
|
244
|
+
"""Run the test that uses this fixture on each available array API library.
|
206
245
|
|
246
|
+
You can select all and only the tests that use the `xp` fixture by
|
247
|
+
passing `-m array_api_backends` to pytest.
|
207
248
|
|
208
|
-
|
209
|
-
|
210
|
-
# do not allow multiple backends
|
211
|
-
args_ = request.keywords[f'{skip_or_xfail}_xp_backends'].args
|
212
|
-
if len(args_) > 1:
|
213
|
-
# np_only / cpu_only has args=(), otherwise it's ('numpy',)
|
214
|
-
# and we do not allow ('numpy', 'cupy')
|
215
|
-
raise ValueError(f"multiple backends: {args_}")
|
216
|
-
|
217
|
-
markers = list(request.node.iter_markers(f'{skip_or_xfail}_xp_backends'))
|
218
|
-
backends = []
|
219
|
-
kwargs = {}
|
220
|
-
for marker in markers:
|
221
|
-
if marker.kwargs.get('np_only'):
|
222
|
-
kwargs['np_only'] = True
|
223
|
-
kwargs['exceptions'] = marker.kwargs.get('exceptions', [])
|
224
|
-
elif marker.kwargs.get('cpu_only'):
|
225
|
-
if not kwargs.get('np_only'):
|
226
|
-
# if np_only is given, it is certainly cpu only
|
227
|
-
kwargs['cpu_only'] = True
|
228
|
-
kwargs['exceptions'] = marker.kwargs.get('exceptions', [])
|
229
|
-
|
230
|
-
# add backends, if any
|
231
|
-
if len(marker.args) > 0:
|
232
|
-
backend = marker.args[0] # was a tuple, ('numpy',) etc
|
233
|
-
backends.append(backend)
|
234
|
-
kwargs.update(**{backend: marker.kwargs})
|
249
|
+
You can select where individual tests run through the `@skip_xp_backends`,
|
250
|
+
`@xfail_xp_backends`, and `@skip_xp_invalid_arg` pytest markers.
|
235
251
|
|
236
|
-
|
252
|
+
Please read: https://docs.scipy.org/doc/scipy/dev/api-dev/array_api.html#adding-tests
|
253
|
+
"""
|
254
|
+
# Read all @pytest.marks.skip_xp_backends markers that decorate to the test,
|
255
|
+
# if any, and raise pytest.skip() if the current xp is in the list.
|
256
|
+
skip_or_xfail_xp_backends(request, "skip")
|
257
|
+
# Read all @pytest.marks.xfail_xp_backends markers that decorate the test,
|
258
|
+
# if any, and raise pytest.xfail() if the current xp is in the list.
|
259
|
+
skip_or_xfail_xp_backends(request, "xfail")
|
260
|
+
|
261
|
+
xp = request.param
|
262
|
+
# Potentially wrap namespace with array_api_compat
|
263
|
+
xp = array_namespace(xp.empty(0))
|
264
|
+
|
265
|
+
if SCIPY_ARRAY_API:
|
266
|
+
# If request.param==jax.numpy, wrap tested functions in jax.jit
|
267
|
+
patch_lazy_xp_functions(
|
268
|
+
xp=request.param, request=request, monkeypatch=monkeypatch
|
269
|
+
)
|
237
270
|
|
271
|
+
# Throughout all calls to assert_almost_equal, assert_array_almost_equal, and
|
272
|
+
# xp_assert_* functions, test that the array namespace is xp in both the
|
273
|
+
# expected and actual arrays. This is to detect the case where both arrays are
|
274
|
+
# erroneously just plain numpy while xp is something else.
|
275
|
+
with default_xp(xp):
|
276
|
+
yield xp
|
277
|
+
else:
|
278
|
+
yield xp
|
238
279
|
|
239
|
-
@pytest.fixture
|
240
|
-
def skip_xp_backends(xp, request):
|
241
|
-
"""skip_xp_backends(backend=None, reason=None, np_only=False, cpu_only=False, exceptions=None)
|
242
280
|
|
243
|
-
|
281
|
+
skip_xp_invalid_arg = pytest.mark.skipif(SCIPY_ARRAY_API,
|
282
|
+
reason = ('Test involves masked arrays, object arrays, or other types '
|
283
|
+
'that are not valid input when `SCIPY_ARRAY_API` is used.'))
|
244
284
|
|
245
|
-
See ``skip_or_xfail_backends`` docstring for details. Note that, contrary to
|
246
|
-
``skip_or_xfail_backends``, the ``backend`` and ``reason`` arguments are optional
|
247
|
-
single strings: this function only skips a single backend at a time.
|
248
|
-
To skip multiple backends, provide multiple decorators.
|
249
|
-
""" # noqa: E501
|
250
|
-
if "skip_xp_backends" not in request.keywords:
|
251
|
-
return
|
252
285
|
|
253
|
-
|
254
|
-
|
286
|
+
def _backends_kwargs_from_request(request, skip_or_xfail):
|
287
|
+
"""A helper for {skip,xfail}_xp_backends.
|
255
288
|
|
289
|
+
Return dict of {backend to skip/xfail: top reason to skip/xfail it}
|
290
|
+
"""
|
291
|
+
markers = list(request.node.iter_markers(f'{skip_or_xfail}_xp_backends'))
|
292
|
+
reasons = {backend: [] for backend in xp_known_backends}
|
256
293
|
|
257
|
-
|
258
|
-
|
259
|
-
|
294
|
+
for marker in markers:
|
295
|
+
invalid_kwargs = set(marker.kwargs) - {
|
296
|
+
"cpu_only", "np_only", "eager_only", "reason", "exceptions"}
|
297
|
+
if invalid_kwargs:
|
298
|
+
raise TypeError(f"Invalid kwargs: {invalid_kwargs}")
|
299
|
+
|
300
|
+
exceptions = set(marker.kwargs.get('exceptions', []))
|
301
|
+
invalid_exceptions = exceptions - xp_known_backends
|
302
|
+
if (invalid_exceptions := list(exceptions - xp_known_backends)):
|
303
|
+
raise ValueError(f"Unknown backend(s): {invalid_exceptions}; "
|
304
|
+
f"must be a subset of {list(xp_known_backends)}")
|
305
|
+
|
306
|
+
if marker.kwargs.get('np_only', False):
|
307
|
+
reason = marker.kwargs.get("reason") or "do not run with non-NumPy backends"
|
308
|
+
for backend in xp_skip_np_only_backends - exceptions:
|
309
|
+
reasons[backend].append(reason)
|
310
|
+
|
311
|
+
elif marker.kwargs.get('cpu_only', False):
|
312
|
+
reason = marker.kwargs.get("reason") or (
|
313
|
+
"no array-agnostic implementation or delegation available "
|
314
|
+
"for this backend and device")
|
315
|
+
for backend in xp_skip_cpu_only_backends - exceptions:
|
316
|
+
reasons[backend].append(reason)
|
317
|
+
|
318
|
+
elif marker.kwargs.get('eager_only', False):
|
319
|
+
reason = marker.kwargs.get("reason") or (
|
320
|
+
"eager checks not executed on lazy backends")
|
321
|
+
for backend in xp_skip_eager_only_backends - exceptions:
|
322
|
+
reasons[backend].append(reason)
|
260
323
|
|
261
|
-
|
324
|
+
# add backends, if any
|
325
|
+
if len(marker.args) == 1:
|
326
|
+
backend = marker.args[0]
|
327
|
+
if backend not in xp_known_backends:
|
328
|
+
raise ValueError(f"Unknown backend: {backend}; "
|
329
|
+
f"must be one of {list(xp_known_backends)}")
|
330
|
+
reason = marker.kwargs.get("reason") or (
|
331
|
+
f"do not run with array API backend: {backend}")
|
332
|
+
# reason overrides the ones from cpu_only, np_only, and eager_only.
|
333
|
+
# This is regardless of order of appearence of the markers.
|
334
|
+
reasons[backend].insert(0, reason)
|
335
|
+
|
336
|
+
for kwarg in ("cpu_only", "np_only", "eager_only", "exceptions"):
|
337
|
+
if kwarg in marker.kwargs:
|
338
|
+
raise ValueError(f"{kwarg} is mutually exclusive with {backend}")
|
339
|
+
|
340
|
+
elif len(marker.args) > 1:
|
341
|
+
raise ValueError(
|
342
|
+
f"Please specify only one backend per marker: {marker.args}"
|
343
|
+
)
|
344
|
+
|
345
|
+
return {backend: backend_reasons[0]
|
346
|
+
for backend, backend_reasons in reasons.items()
|
347
|
+
if backend_reasons}
|
348
|
+
|
349
|
+
|
350
|
+
def skip_or_xfail_xp_backends(request: pytest.FixtureRequest,
|
351
|
+
skip_or_xfail: Literal['skip', 'xfail']) -> None:
|
352
|
+
"""
|
353
|
+
Helper of the `xp` fixture.
|
354
|
+
Skip or xfail based on the ``skip_xp_backends`` or ``xfail_xp_backends`` markers.
|
262
355
|
|
263
|
-
See
|
264
|
-
``skip_or_xfail_backends``, the ``backend`` and ``reason`` arguments are optional
|
265
|
-
single strings: this function only xfails a single backend at a time.
|
266
|
-
To xfail multiple backends, provide multiple decorators.
|
267
|
-
""" # noqa: E501
|
268
|
-
if "xfail_xp_backends" not in request.keywords:
|
269
|
-
return
|
270
|
-
backends, kwargs = _backends_kwargs_from_request(request, skip_or_xfail='xfail')
|
271
|
-
skip_or_xfail_xp_backends(xp, backends, kwargs, skip_or_xfail='xfail')
|
356
|
+
See the "Support for the array API standard" docs page for usage examples.
|
272
357
|
|
358
|
+
Usage
|
359
|
+
-----
|
360
|
+
::
|
361
|
+
skip_xp_backends = pytest.mark.skip_xp_backends
|
362
|
+
xfail_xp_backends = pytest.mark.xfail_xp_backends
|
363
|
+
...
|
273
364
|
|
274
|
-
|
275
|
-
|
276
|
-
|
365
|
+
@skip_xp_backends(backend, *, reason=None)
|
366
|
+
@skip_xp_backends(*, cpu_only=True, exceptions=(), reason=None)
|
367
|
+
@skip_xp_backends(*, eager_only=True, exceptions=(), reason=None)
|
368
|
+
@skip_xp_backends(*, np_only=True, exceptions=(), reason=None)
|
277
369
|
|
278
|
-
|
370
|
+
@xfail_xp_backends(backend, *, reason=None)
|
371
|
+
@xfail_xp_backends(*, cpu_only=True, exceptions=(), reason=None)
|
372
|
+
@xfail_xp_backends(*, eager_only=True, exceptions=(), reason=None)
|
373
|
+
@xfail_xp_backends(*, np_only=True, exceptions=(), reason=None)
|
279
374
|
|
280
375
|
Parameters
|
281
376
|
----------
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
377
|
+
backend : str, optional
|
378
|
+
Backend to skip/xfail, e.g. ``"torch"``.
|
379
|
+
Mutually exclusive with ``cpu_only``, ``eager_only``, and ``np_only``.
|
380
|
+
cpu_only : bool, optional
|
381
|
+
When ``True``, the test is skipped/xfailed on non-CPU devices,
|
382
|
+
minus exceptions. Mutually exclusive with ``backend``.
|
383
|
+
eager_only : bool, optional
|
384
|
+
When ``True``, the test is skipped/xfailed for lazy backends, e.g. those
|
385
|
+
with major caveats when invoking ``__array__``, ``__bool__``, ``__float__``,
|
386
|
+
or ``__complex__``, minus exceptions. Mutually exclusive with ``backend``.
|
292
387
|
np_only : bool, optional
|
293
388
|
When ``True``, the test is skipped/xfailed for all backends other
|
294
|
-
than the default NumPy backend
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
but any ``backends`` will also be skipped on the CPU.
|
301
|
-
Default: ``False``.
|
302
|
-
exceptions : list, optional
|
303
|
-
A list of exceptions for use with ``cpu_only`` or ``np_only``.
|
389
|
+
than the default NumPy backend and the exceptions.
|
390
|
+
Mutually exclusive with ``backend``. Implies ``cpu_only`` and ``eager_only``.
|
391
|
+
reason : str, optional
|
392
|
+
A reason for the skip/xfail. If omitted, a default reason is used.
|
393
|
+
exceptions : list[str], optional
|
394
|
+
A list of exceptions for use with ``cpu_only``, ``eager_only``, or ``np_only``.
|
304
395
|
This should be provided when delegation is implemented for some,
|
305
396
|
but not all, non-CPU/non-NumPy backends.
|
306
|
-
skip_or_xfail : str
|
307
|
-
``'skip'`` to skip, ``'xfail'`` to xfail.
|
308
397
|
"""
|
309
|
-
skip_or_xfail
|
310
|
-
np_only = kwargs.get("np_only", False)
|
311
|
-
cpu_only = kwargs.get("cpu_only", False)
|
312
|
-
exceptions = kwargs.get("exceptions", [])
|
313
|
-
|
314
|
-
if reasons := kwargs.get("reasons"):
|
315
|
-
raise ValueError(f"provide a single `reason=` kwarg; got {reasons=} instead")
|
316
|
-
|
317
|
-
# input validation
|
318
|
-
if np_only and cpu_only:
|
319
|
-
# np_only is a stricter subset of cpu_only
|
320
|
-
cpu_only = False
|
321
|
-
if exceptions and not (cpu_only or np_only):
|
322
|
-
raise ValueError("`exceptions` is only valid alongside `cpu_only` or `np_only`")
|
323
|
-
|
324
|
-
if np_only:
|
325
|
-
reason = kwargs.get("reason", "do not run with non-NumPy backends.")
|
326
|
-
if not isinstance(reason, str) and len(reason) > 1:
|
327
|
-
raise ValueError("please provide a singleton `reason` "
|
328
|
-
"when using `np_only`")
|
329
|
-
if xp.__name__ != 'numpy' and xp.__name__ not in exceptions:
|
330
|
-
skip_or_xfail(reason=reason)
|
398
|
+
if f"{skip_or_xfail}_xp_backends" not in request.keywords:
|
331
399
|
return
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
400
|
+
|
401
|
+
skip_xfail_reasons = _backends_kwargs_from_request(
|
402
|
+
request, skip_or_xfail=skip_or_xfail
|
403
|
+
)
|
404
|
+
xp = request.param
|
405
|
+
if xp.__name__ in skip_xfail_reasons:
|
406
|
+
reason = skip_xfail_reasons[xp.__name__]
|
407
|
+
assert reason # Default reason applied above
|
408
|
+
skip_or_xfail = getattr(pytest, skip_or_xfail)
|
409
|
+
skip_or_xfail(reason=reason)
|
410
|
+
|
411
|
+
|
412
|
+
@pytest.fixture
|
413
|
+
def devices(xp):
|
414
|
+
"""Fixture that returns a list of all devices for the backend, plus None.
|
415
|
+
Used to test input->output device propagation.
|
416
|
+
|
417
|
+
Usage
|
418
|
+
-----
|
419
|
+
from scipy._lib._array_api import xp_device
|
420
|
+
|
421
|
+
def test_device(xp, devices):
|
422
|
+
for d in devices:
|
423
|
+
x = xp.asarray(..., device=d)
|
424
|
+
y = f(x)
|
425
|
+
assert xp_device(y) == xp_device(x)
|
426
|
+
"""
|
427
|
+
if is_cupy(xp):
|
428
|
+
# CuPy does not support devices other than the current one
|
429
|
+
# data-apis/array-api-compat#293
|
430
|
+
pytest.xfail(reason="data-apis/array-api-compat#293")
|
431
|
+
if is_dask(xp):
|
432
|
+
# Skip dummy DASK_DEVICE from array-api-compat, which does not propagate
|
433
|
+
return ["cpu", None]
|
434
|
+
if is_jax(xp):
|
435
|
+
# The .device attribute is not accessible inside jax.jit; the consequence
|
436
|
+
# (downstream of array-api-compat hacks) is that a non-default device in
|
437
|
+
# input is not guaranteed to propagate to the output even if the scipy code
|
438
|
+
# states `device=xp_device(arg)`` in all array creation functions.
|
439
|
+
# While this issue is specific to jax.jit, it would be unnecessarily
|
440
|
+
# verbose to skip the test for each jit-capable function and run it for
|
441
|
+
# those that only support eager mode.
|
442
|
+
pytest.xfail(reason="jax-ml/jax#26000")
|
443
|
+
|
444
|
+
return xp.__array_namespace_info__().devices() + [None]
|
355
445
|
|
356
446
|
|
357
447
|
# Following the approach of NumPy's conftest.py...
|
@@ -521,12 +611,25 @@ if HAVE_SCPDT:
|
|
521
611
|
# equivalent to "pytest --ignore=path/to/file"
|
522
612
|
"scipy/special/_precompute",
|
523
613
|
"scipy/interpolate/_interpnd_info.py",
|
614
|
+
"scipy/interpolate/_rbfinterp_pythran.py",
|
615
|
+
"scipy/_build_utils/tempita.py",
|
524
616
|
"scipy/_lib/array_api_compat",
|
525
617
|
"scipy/_lib/highs",
|
526
618
|
"scipy/_lib/unuran",
|
527
619
|
"scipy/_lib/_gcutils.py",
|
528
620
|
"scipy/_lib/doccer.py",
|
529
621
|
"scipy/_lib/_uarray",
|
622
|
+
"scipy/linalg/_cython_signature_generator.py",
|
623
|
+
"scipy/linalg/_generate_pyx.py",
|
624
|
+
"scipy/linalg/_linalg_pythran.py",
|
625
|
+
"scipy/linalg/_matfuncs_sqrtm_triu.py",
|
626
|
+
"scipy/ndimage/utils/generate_label_testvectors.py",
|
627
|
+
"scipy/optimize/_group_columns.py",
|
628
|
+
"scipy/optimize/_max_len_seq_inner.py",
|
629
|
+
"scipy/signal/_max_len_seq_inner.py",
|
630
|
+
"scipy/sparse/_generate_sparsetools.py",
|
631
|
+
"scipy/special/_generate_pyx.py",
|
632
|
+
"scipy/stats/_stats_pythran.py",
|
530
633
|
]
|
531
634
|
|
532
635
|
dt_config.pytest_extra_xfail = {
|
@@ -549,4 +652,7 @@ if HAVE_SCPDT:
|
|
549
652
|
}
|
550
653
|
|
551
654
|
dt_config.strict_check = True
|
655
|
+
|
656
|
+
# ignore Matplotlib's `ax.text`:
|
657
|
+
dt_config.stopwords.add('.text(')
|
552
658
|
############################################################################
|
scipy/constants/_constants.py
CHANGED
@@ -15,7 +15,7 @@ from ._codata import value as _cd
|
|
15
15
|
if TYPE_CHECKING:
|
16
16
|
import numpy.typing as npt
|
17
17
|
|
18
|
-
from scipy._lib._array_api import array_namespace, _asarray
|
18
|
+
from scipy._lib._array_api import array_namespace, _asarray, xp_capabilities
|
19
19
|
|
20
20
|
|
21
21
|
"""
|
@@ -225,6 +225,7 @@ kgf = kilogram_force = g # * 1 kg
|
|
225
225
|
# functions for conversions that are not linear
|
226
226
|
|
227
227
|
|
228
|
+
@xp_capabilities()
|
228
229
|
def convert_temperature(
|
229
230
|
val: "npt.ArrayLike",
|
230
231
|
old_scale: str,
|
@@ -304,6 +305,7 @@ def convert_temperature(
|
|
304
305
|
# optics
|
305
306
|
|
306
307
|
|
308
|
+
@xp_capabilities()
|
307
309
|
def lambda2nu(lambda_: "npt.ArrayLike") -> Any:
|
308
310
|
"""
|
309
311
|
Convert wavelength to optical frequency
|
@@ -335,6 +337,7 @@ def lambda2nu(lambda_: "npt.ArrayLike") -> Any:
|
|
335
337
|
return c / _asarray(lambda_, xp=xp, subok=True)
|
336
338
|
|
337
339
|
|
340
|
+
@xp_capabilities()
|
338
341
|
def nu2lambda(nu: "npt.ArrayLike") -> Any:
|
339
342
|
"""
|
340
343
|
Convert optical frequency to wavelength.
|
@@ -31,8 +31,8 @@ def test_basic_table_parse():
|
|
31
31
|
|
32
32
|
|
33
33
|
def test_basic_lookup():
|
34
|
-
assert_equal('
|
35
|
-
|
34
|
+
assert_equal('{} {}'.format(int(_cd.value('speed of light in vacuum')),
|
35
|
+
_cd.unit('speed of light in vacuum')),
|
36
36
|
'299792458 m s^-1')
|
37
37
|
|
38
38
|
|
@@ -1,15 +1,13 @@
|
|
1
1
|
import pytest
|
2
2
|
|
3
3
|
import scipy.constants as sc
|
4
|
-
from scipy.conftest import array_api_compatible
|
5
4
|
from scipy._lib._array_api_no_0d import xp_assert_equal, xp_assert_close
|
6
|
-
from
|
5
|
+
from scipy._lib._array_api import make_xp_test_case
|
7
6
|
|
8
|
-
|
9
|
-
pytestmark = [array_api_compatible, pytest.mark.usefixtures("skip_xp_backends")]
|
10
|
-
skip_xp_backends = pytest.mark.skip_xp_backends
|
7
|
+
lazy_xp_modules = [sc]
|
11
8
|
|
12
9
|
|
10
|
+
@make_xp_test_case(sc.convert_temperature)
|
13
11
|
class TestConvertTemperature:
|
14
12
|
def test_convert_temperature(self, xp):
|
15
13
|
xp_assert_equal(sc.convert_temperature(xp.asarray(32.), 'f', 'Celsius'),
|
@@ -52,39 +50,34 @@ class TestConvertTemperature:
|
|
52
50
|
'rankine', 'kelvin'),
|
53
51
|
xp.asarray([273.15, 0.], dtype=xp.float64), rtol=0., atol=1e-13)
|
54
52
|
|
55
|
-
@skip_xp_backends(np_only=True, reason='Python list input uses NumPy backend')
|
56
53
|
def test_convert_temperature_array_like(self):
|
57
|
-
|
54
|
+
xp_assert_close(sc.convert_temperature([491.67, 0.], 'rankine', 'kelvin'),
|
58
55
|
[273.15, 0.], rtol=0., atol=1e-13)
|
59
56
|
|
60
57
|
|
61
|
-
|
62
|
-
def test_convert_temperature_errors(self, xp):
|
58
|
+
def test_convert_temperature_errors(self):
|
63
59
|
with pytest.raises(NotImplementedError, match="old_scale="):
|
64
60
|
sc.convert_temperature(1, old_scale="cheddar", new_scale="kelvin")
|
65
61
|
with pytest.raises(NotImplementedError, match="new_scale="):
|
66
62
|
sc.convert_temperature(1, old_scale="kelvin", new_scale="brie")
|
67
63
|
|
68
64
|
|
65
|
+
@make_xp_test_case(sc.lambda2nu)
|
69
66
|
class TestLambdaToNu:
|
70
67
|
def test_lambda_to_nu(self, xp):
|
71
68
|
xp_assert_equal(sc.lambda2nu(xp.asarray([sc.speed_of_light, 1])),
|
72
69
|
xp.asarray([1, sc.speed_of_light]))
|
73
70
|
|
74
71
|
|
75
|
-
|
76
|
-
|
77
|
-
assert_allclose(sc.lambda2nu([sc.speed_of_light, 1]),
|
78
|
-
[1, sc.speed_of_light])
|
72
|
+
def test_lambda_to_nu_array_like(self):
|
73
|
+
xp_assert_close(sc.lambda2nu([sc.speed_of_light, 1]), [1, sc.speed_of_light])
|
79
74
|
|
80
75
|
|
76
|
+
@make_xp_test_case(sc.nu2lambda)
|
81
77
|
class TestNuToLambda:
|
82
78
|
def test_nu_to_lambda(self, xp):
|
83
79
|
xp_assert_equal(sc.nu2lambda(xp.asarray([sc.speed_of_light, 1])),
|
84
80
|
xp.asarray([1, sc.speed_of_light]))
|
85
81
|
|
86
|
-
|
87
|
-
|
88
|
-
assert_allclose(sc.nu2lambda([sc.speed_of_light, 1]),
|
89
|
-
[1, sc.speed_of_light])
|
90
|
-
|
82
|
+
def test_nu_to_lambda_array_like(self):
|
83
|
+
xp_assert_close(sc.nu2lambda([sc.speed_of_light, 1]), [1, sc.speed_of_light])
|