scipy 1.15.3__cp313-cp313-musllinux_1_2_aarch64.whl → 1.16.0__cp313-cp313-musllinux_1_2_aarch64.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.
Files changed (642) hide show
  1. scipy/__config__.py +11 -11
  2. scipy/__init__.py +3 -6
  3. scipy/_cyutility.cpython-313-aarch64-linux-musl.so +0 -0
  4. scipy/_lib/_array_api.py +486 -161
  5. scipy/_lib/_array_api_compat_vendor.py +9 -0
  6. scipy/_lib/_bunch.py +4 -0
  7. scipy/_lib/_ccallback_c.cpython-313-aarch64-linux-musl.so +0 -0
  8. scipy/_lib/_docscrape.py +1 -1
  9. scipy/_lib/_elementwise_iterative_method.py +15 -26
  10. scipy/_lib/_fpumode.cpython-313-aarch64-linux-musl.so +0 -0
  11. scipy/_lib/_sparse.py +41 -0
  12. scipy/_lib/_test_ccallback.cpython-313-aarch64-linux-musl.so +0 -0
  13. scipy/_lib/_test_deprecation_call.cpython-313-aarch64-linux-musl.so +0 -0
  14. scipy/_lib/_test_deprecation_def.cpython-313-aarch64-linux-musl.so +0 -0
  15. scipy/_lib/_testutils.py +6 -2
  16. scipy/_lib/_uarray/_uarray.cpython-313-aarch64-linux-musl.so +0 -0
  17. scipy/_lib/_util.py +222 -125
  18. scipy/_lib/array_api_compat/__init__.py +4 -4
  19. scipy/_lib/array_api_compat/_internal.py +19 -6
  20. scipy/_lib/array_api_compat/common/__init__.py +1 -1
  21. scipy/_lib/array_api_compat/common/_aliases.py +365 -193
  22. scipy/_lib/array_api_compat/common/_fft.py +94 -64
  23. scipy/_lib/array_api_compat/common/_helpers.py +413 -180
  24. scipy/_lib/array_api_compat/common/_linalg.py +116 -40
  25. scipy/_lib/array_api_compat/common/_typing.py +179 -10
  26. scipy/_lib/array_api_compat/cupy/__init__.py +1 -4
  27. scipy/_lib/array_api_compat/cupy/_aliases.py +61 -41
  28. scipy/_lib/array_api_compat/cupy/_info.py +16 -6
  29. scipy/_lib/array_api_compat/cupy/_typing.py +24 -39
  30. scipy/_lib/array_api_compat/dask/array/__init__.py +6 -3
  31. scipy/_lib/array_api_compat/dask/array/_aliases.py +267 -108
  32. scipy/_lib/array_api_compat/dask/array/_info.py +105 -34
  33. scipy/_lib/array_api_compat/dask/array/fft.py +5 -8
  34. scipy/_lib/array_api_compat/dask/array/linalg.py +21 -22
  35. scipy/_lib/array_api_compat/numpy/__init__.py +13 -15
  36. scipy/_lib/array_api_compat/numpy/_aliases.py +98 -49
  37. scipy/_lib/array_api_compat/numpy/_info.py +36 -16
  38. scipy/_lib/array_api_compat/numpy/_typing.py +27 -43
  39. scipy/_lib/array_api_compat/numpy/fft.py +11 -5
  40. scipy/_lib/array_api_compat/numpy/linalg.py +75 -22
  41. scipy/_lib/array_api_compat/torch/__init__.py +3 -5
  42. scipy/_lib/array_api_compat/torch/_aliases.py +262 -159
  43. scipy/_lib/array_api_compat/torch/_info.py +27 -16
  44. scipy/_lib/array_api_compat/torch/_typing.py +3 -0
  45. scipy/_lib/array_api_compat/torch/fft.py +17 -18
  46. scipy/_lib/array_api_compat/torch/linalg.py +16 -16
  47. scipy/_lib/array_api_extra/__init__.py +26 -3
  48. scipy/_lib/array_api_extra/_delegation.py +171 -0
  49. scipy/_lib/array_api_extra/_lib/__init__.py +1 -0
  50. scipy/_lib/array_api_extra/_lib/_at.py +463 -0
  51. scipy/_lib/array_api_extra/_lib/_backends.py +46 -0
  52. scipy/_lib/array_api_extra/_lib/_funcs.py +937 -0
  53. scipy/_lib/array_api_extra/_lib/_lazy.py +357 -0
  54. scipy/_lib/array_api_extra/_lib/_testing.py +278 -0
  55. scipy/_lib/array_api_extra/_lib/_utils/__init__.py +1 -0
  56. scipy/_lib/array_api_extra/_lib/_utils/_compat.py +74 -0
  57. scipy/_lib/array_api_extra/_lib/_utils/_compat.pyi +45 -0
  58. scipy/_lib/array_api_extra/_lib/_utils/_helpers.py +559 -0
  59. scipy/_lib/array_api_extra/_lib/_utils/_typing.py +10 -0
  60. scipy/_lib/array_api_extra/_lib/_utils/_typing.pyi +105 -0
  61. scipy/_lib/array_api_extra/testing.py +359 -0
  62. scipy/_lib/decorator.py +2 -2
  63. scipy/_lib/doccer.py +1 -7
  64. scipy/_lib/messagestream.cpython-313-aarch64-linux-musl.so +0 -0
  65. scipy/_lib/pyprima/__init__.py +212 -0
  66. scipy/_lib/pyprima/cobyla/__init__.py +0 -0
  67. scipy/_lib/pyprima/cobyla/cobyla.py +559 -0
  68. scipy/_lib/pyprima/cobyla/cobylb.py +714 -0
  69. scipy/_lib/pyprima/cobyla/geometry.py +226 -0
  70. scipy/_lib/pyprima/cobyla/initialize.py +215 -0
  71. scipy/_lib/pyprima/cobyla/trustregion.py +492 -0
  72. scipy/_lib/pyprima/cobyla/update.py +289 -0
  73. scipy/_lib/pyprima/common/__init__.py +0 -0
  74. scipy/_lib/pyprima/common/_bounds.py +34 -0
  75. scipy/_lib/pyprima/common/_linear_constraints.py +46 -0
  76. scipy/_lib/pyprima/common/_nonlinear_constraints.py +54 -0
  77. scipy/_lib/pyprima/common/_project.py +173 -0
  78. scipy/_lib/pyprima/common/checkbreak.py +93 -0
  79. scipy/_lib/pyprima/common/consts.py +47 -0
  80. scipy/_lib/pyprima/common/evaluate.py +99 -0
  81. scipy/_lib/pyprima/common/history.py +38 -0
  82. scipy/_lib/pyprima/common/infos.py +30 -0
  83. scipy/_lib/pyprima/common/linalg.py +435 -0
  84. scipy/_lib/pyprima/common/message.py +290 -0
  85. scipy/_lib/pyprima/common/powalg.py +131 -0
  86. scipy/_lib/pyprima/common/preproc.py +277 -0
  87. scipy/_lib/pyprima/common/present.py +5 -0
  88. scipy/_lib/pyprima/common/ratio.py +54 -0
  89. scipy/_lib/pyprima/common/redrho.py +47 -0
  90. scipy/_lib/pyprima/common/selectx.py +296 -0
  91. scipy/_lib/tests/test__util.py +105 -121
  92. scipy/_lib/tests/test_array_api.py +166 -35
  93. scipy/_lib/tests/test_bunch.py +7 -0
  94. scipy/_lib/tests/test_ccallback.py +2 -10
  95. scipy/_lib/tests/test_public_api.py +13 -0
  96. scipy/cluster/_hierarchy.cpython-313-aarch64-linux-musl.so +0 -0
  97. scipy/cluster/_optimal_leaf_ordering.cpython-313-aarch64-linux-musl.so +0 -0
  98. scipy/cluster/_vq.cpython-313-aarch64-linux-musl.so +0 -0
  99. scipy/cluster/hierarchy.py +393 -223
  100. scipy/cluster/tests/test_hierarchy.py +273 -335
  101. scipy/cluster/tests/test_vq.py +45 -61
  102. scipy/cluster/vq.py +39 -35
  103. scipy/conftest.py +282 -151
  104. scipy/constants/_constants.py +4 -1
  105. scipy/constants/tests/test_codata.py +2 -2
  106. scipy/constants/tests/test_constants.py +11 -18
  107. scipy/datasets/_download_all.py +15 -1
  108. scipy/datasets/_fetchers.py +7 -1
  109. scipy/datasets/_utils.py +1 -1
  110. scipy/differentiate/_differentiate.py +25 -25
  111. scipy/differentiate/tests/test_differentiate.py +24 -25
  112. scipy/fft/_basic.py +20 -0
  113. scipy/fft/_helper.py +3 -34
  114. scipy/fft/_pocketfft/helper.py +29 -1
  115. scipy/fft/_pocketfft/pypocketfft.cpython-313-aarch64-linux-musl.so +0 -0
  116. scipy/fft/_pocketfft/tests/test_basic.py +2 -4
  117. scipy/fft/_pocketfft/tests/test_real_transforms.py +4 -4
  118. scipy/fft/_realtransforms.py +13 -0
  119. scipy/fft/tests/test_basic.py +27 -25
  120. scipy/fft/tests/test_fftlog.py +16 -7
  121. scipy/fft/tests/test_helper.py +18 -34
  122. scipy/fft/tests/test_real_transforms.py +8 -10
  123. scipy/fftpack/convolve.cpython-313-aarch64-linux-musl.so +0 -0
  124. scipy/fftpack/tests/test_basic.py +2 -4
  125. scipy/fftpack/tests/test_real_transforms.py +8 -9
  126. scipy/integrate/_bvp.py +9 -3
  127. scipy/integrate/_cubature.py +3 -2
  128. scipy/integrate/_dop.cpython-313-aarch64-linux-musl.so +0 -0
  129. scipy/integrate/_lsoda.cpython-313-aarch64-linux-musl.so +0 -0
  130. scipy/integrate/_ode.py +9 -2
  131. scipy/integrate/_odepack.cpython-313-aarch64-linux-musl.so +0 -0
  132. scipy/integrate/_quad_vec.py +21 -29
  133. scipy/integrate/_quadpack.cpython-313-aarch64-linux-musl.so +0 -0
  134. scipy/integrate/_quadpack_py.py +11 -7
  135. scipy/integrate/_quadrature.py +3 -3
  136. scipy/integrate/_rules/_base.py +2 -2
  137. scipy/integrate/_tanhsinh.py +48 -47
  138. scipy/integrate/_test_multivariate.cpython-313-aarch64-linux-musl.so +0 -0
  139. scipy/integrate/_test_odeint_banded.cpython-313-aarch64-linux-musl.so +0 -0
  140. scipy/integrate/_vode.cpython-313-aarch64-linux-musl.so +0 -0
  141. scipy/integrate/tests/test__quad_vec.py +0 -6
  142. scipy/integrate/tests/test_banded_ode_solvers.py +85 -0
  143. scipy/integrate/tests/test_cubature.py +21 -35
  144. scipy/integrate/tests/test_quadrature.py +6 -8
  145. scipy/integrate/tests/test_tanhsinh.py +56 -48
  146. scipy/interpolate/__init__.py +70 -58
  147. scipy/interpolate/_bary_rational.py +22 -22
  148. scipy/interpolate/_bsplines.py +119 -66
  149. scipy/interpolate/_cubic.py +65 -50
  150. scipy/interpolate/_dfitpack.cpython-313-aarch64-linux-musl.so +0 -0
  151. scipy/interpolate/_dierckx.cpython-313-aarch64-linux-musl.so +0 -0
  152. scipy/interpolate/_fitpack.cpython-313-aarch64-linux-musl.so +0 -0
  153. scipy/interpolate/_fitpack2.py +9 -6
  154. scipy/interpolate/_fitpack_impl.py +32 -26
  155. scipy/interpolate/_fitpack_repro.py +23 -19
  156. scipy/interpolate/_interpnd.cpython-313-aarch64-linux-musl.so +0 -0
  157. scipy/interpolate/_interpolate.py +30 -12
  158. scipy/interpolate/_ndbspline.py +13 -18
  159. scipy/interpolate/_ndgriddata.py +5 -8
  160. scipy/interpolate/_polyint.py +95 -31
  161. scipy/interpolate/_ppoly.cpython-313-aarch64-linux-musl.so +0 -0
  162. scipy/interpolate/_rbf.py +2 -2
  163. scipy/interpolate/_rbfinterp.py +1 -1
  164. scipy/interpolate/_rbfinterp_pythran.cpython-313-aarch64-linux-musl.so +0 -0
  165. scipy/interpolate/_rgi.py +31 -26
  166. scipy/interpolate/_rgi_cython.cpython-313-aarch64-linux-musl.so +0 -0
  167. scipy/interpolate/dfitpack.py +0 -20
  168. scipy/interpolate/interpnd.py +1 -2
  169. scipy/interpolate/tests/test_bary_rational.py +2 -2
  170. scipy/interpolate/tests/test_bsplines.py +97 -1
  171. scipy/interpolate/tests/test_fitpack2.py +39 -1
  172. scipy/interpolate/tests/test_interpnd.py +32 -20
  173. scipy/interpolate/tests/test_interpolate.py +48 -4
  174. scipy/interpolate/tests/test_rgi.py +2 -1
  175. scipy/io/_fast_matrix_market/__init__.py +2 -0
  176. scipy/io/_fast_matrix_market/_fmm_core.cpython-313-aarch64-linux-musl.so +0 -0
  177. scipy/io/_harwell_boeing/_fortran_format_parser.py +19 -16
  178. scipy/io/_harwell_boeing/hb.py +7 -11
  179. scipy/io/_idl.py +5 -7
  180. scipy/io/_netcdf.py +15 -5
  181. scipy/io/_test_fortran.cpython-313-aarch64-linux-musl.so +0 -0
  182. scipy/io/arff/tests/test_arffread.py +3 -3
  183. scipy/io/matlab/__init__.py +5 -3
  184. scipy/io/matlab/_mio.py +4 -1
  185. scipy/io/matlab/_mio5.py +19 -13
  186. scipy/io/matlab/_mio5_utils.cpython-313-aarch64-linux-musl.so +0 -0
  187. scipy/io/matlab/_mio_utils.cpython-313-aarch64-linux-musl.so +0 -0
  188. scipy/io/matlab/_miobase.py +4 -1
  189. scipy/io/matlab/_streams.cpython-313-aarch64-linux-musl.so +0 -0
  190. scipy/io/matlab/tests/test_mio.py +46 -18
  191. scipy/io/matlab/tests/test_mio_funcs.py +1 -1
  192. scipy/io/tests/test_mmio.py +7 -1
  193. scipy/io/tests/test_wavfile.py +41 -0
  194. scipy/io/wavfile.py +57 -10
  195. scipy/linalg/_basic.py +113 -86
  196. scipy/linalg/_cythonized_array_utils.cpython-313-aarch64-linux-musl.so +0 -0
  197. scipy/linalg/_decomp.py +22 -9
  198. scipy/linalg/_decomp_cholesky.py +28 -13
  199. scipy/linalg/_decomp_cossin.py +45 -30
  200. scipy/linalg/_decomp_interpolative.cpython-313-aarch64-linux-musl.so +0 -0
  201. scipy/linalg/_decomp_ldl.py +4 -1
  202. scipy/linalg/_decomp_lu.py +18 -6
  203. scipy/linalg/_decomp_lu_cython.cpython-313-aarch64-linux-musl.so +0 -0
  204. scipy/linalg/_decomp_polar.py +2 -0
  205. scipy/linalg/_decomp_qr.py +6 -2
  206. scipy/linalg/_decomp_qz.py +3 -0
  207. scipy/linalg/_decomp_schur.py +3 -1
  208. scipy/linalg/_decomp_svd.py +13 -2
  209. scipy/linalg/_decomp_update.cpython-313-aarch64-linux-musl.so +0 -0
  210. scipy/linalg/_expm_frechet.py +4 -0
  211. scipy/linalg/_fblas.cpython-313-aarch64-linux-musl.so +0 -0
  212. scipy/linalg/_flapack.cpython-313-aarch64-linux-musl.so +0 -0
  213. scipy/linalg/_linalg_pythran.cpython-313-aarch64-linux-musl.so +0 -0
  214. scipy/linalg/_matfuncs.py +187 -4
  215. scipy/linalg/_matfuncs_expm.cpython-313-aarch64-linux-musl.so +0 -0
  216. scipy/linalg/_matfuncs_schur_sqrtm.cpython-313-aarch64-linux-musl.so +0 -0
  217. scipy/linalg/_matfuncs_sqrtm.py +1 -99
  218. scipy/linalg/_matfuncs_sqrtm_triu.cpython-313-aarch64-linux-musl.so +0 -0
  219. scipy/linalg/_procrustes.py +2 -0
  220. scipy/linalg/_sketches.py +17 -6
  221. scipy/linalg/_solve_toeplitz.cpython-313-aarch64-linux-musl.so +0 -0
  222. scipy/linalg/_solvers.py +7 -2
  223. scipy/linalg/_special_matrices.py +26 -36
  224. scipy/linalg/blas.py +35 -24
  225. scipy/linalg/cython_blas.cpython-313-aarch64-linux-musl.so +0 -0
  226. scipy/linalg/cython_lapack.cpython-313-aarch64-linux-musl.so +0 -0
  227. scipy/linalg/lapack.py +22 -2
  228. scipy/linalg/tests/_cython_examples/meson.build +7 -0
  229. scipy/linalg/tests/test_basic.py +31 -16
  230. scipy/linalg/tests/test_batch.py +588 -0
  231. scipy/linalg/tests/test_cythonized_array_utils.py +0 -2
  232. scipy/linalg/tests/test_decomp.py +40 -3
  233. scipy/linalg/tests/test_decomp_cossin.py +14 -0
  234. scipy/linalg/tests/test_decomp_ldl.py +1 -1
  235. scipy/linalg/tests/test_lapack.py +115 -7
  236. scipy/linalg/tests/test_matfuncs.py +157 -102
  237. scipy/linalg/tests/test_procrustes.py +0 -7
  238. scipy/linalg/tests/test_solve_toeplitz.py +1 -1
  239. scipy/linalg/tests/test_special_matrices.py +1 -5
  240. scipy/ndimage/__init__.py +1 -0
  241. scipy/ndimage/_ctest.cpython-313-aarch64-linux-musl.so +0 -0
  242. scipy/ndimage/_cytest.cpython-313-aarch64-linux-musl.so +0 -0
  243. scipy/ndimage/_delegators.py +8 -2
  244. scipy/ndimage/_filters.py +453 -5
  245. scipy/ndimage/_interpolation.py +36 -6
  246. scipy/ndimage/_measurements.py +4 -2
  247. scipy/ndimage/_morphology.py +5 -0
  248. scipy/ndimage/_nd_image.cpython-313-aarch64-linux-musl.so +0 -0
  249. scipy/ndimage/_ni_docstrings.py +5 -1
  250. scipy/ndimage/_ni_label.cpython-313-aarch64-linux-musl.so +0 -0
  251. scipy/ndimage/_ni_support.py +1 -5
  252. scipy/ndimage/_rank_filter_1d.cpython-313-aarch64-linux-musl.so +0 -0
  253. scipy/ndimage/_support_alternative_backends.py +18 -6
  254. scipy/ndimage/tests/test_filters.py +370 -259
  255. scipy/ndimage/tests/test_fourier.py +7 -9
  256. scipy/ndimage/tests/test_interpolation.py +68 -61
  257. scipy/ndimage/tests/test_measurements.py +18 -35
  258. scipy/ndimage/tests/test_morphology.py +143 -131
  259. scipy/ndimage/tests/test_splines.py +1 -3
  260. scipy/odr/__odrpack.cpython-313-aarch64-linux-musl.so +0 -0
  261. scipy/optimize/_basinhopping.py +13 -7
  262. scipy/optimize/_bglu_dense.cpython-313-aarch64-linux-musl.so +0 -0
  263. scipy/optimize/_bracket.py +17 -24
  264. scipy/optimize/_chandrupatla.py +9 -10
  265. scipy/optimize/_cobyla_py.py +104 -123
  266. scipy/optimize/_constraints.py +14 -10
  267. scipy/optimize/_differentiable_functions.py +371 -230
  268. scipy/optimize/_differentialevolution.py +4 -3
  269. scipy/optimize/_direct.cpython-313-aarch64-linux-musl.so +0 -0
  270. scipy/optimize/_dual_annealing.py +1 -1
  271. scipy/optimize/_elementwise.py +1 -4
  272. scipy/optimize/_group_columns.cpython-313-aarch64-linux-musl.so +0 -0
  273. scipy/optimize/_highspy/_core.cpython-313-aarch64-linux-musl.so +0 -0
  274. scipy/optimize/_highspy/_highs_options.cpython-313-aarch64-linux-musl.so +0 -0
  275. scipy/optimize/_lbfgsb.cpython-313-aarch64-linux-musl.so +0 -0
  276. scipy/optimize/_lbfgsb_py.py +80 -24
  277. scipy/optimize/_linprog_doc.py +2 -2
  278. scipy/optimize/_linprog_highs.py +2 -2
  279. scipy/optimize/_linprog_ip.py +25 -10
  280. scipy/optimize/_linprog_util.py +14 -16
  281. scipy/optimize/_lsap.cpython-313-aarch64-linux-musl.so +0 -0
  282. scipy/optimize/_lsq/common.py +3 -3
  283. scipy/optimize/_lsq/dogbox.py +16 -2
  284. scipy/optimize/_lsq/givens_elimination.cpython-313-aarch64-linux-musl.so +0 -0
  285. scipy/optimize/_lsq/least_squares.py +198 -126
  286. scipy/optimize/_lsq/lsq_linear.py +6 -6
  287. scipy/optimize/_lsq/trf.py +35 -8
  288. scipy/optimize/_milp.py +3 -1
  289. scipy/optimize/_minimize.py +105 -36
  290. scipy/optimize/_minpack.cpython-313-aarch64-linux-musl.so +0 -0
  291. scipy/optimize/_minpack_py.py +21 -14
  292. scipy/optimize/_moduleTNC.cpython-313-aarch64-linux-musl.so +0 -0
  293. scipy/optimize/_nnls.py +20 -21
  294. scipy/optimize/_nonlin.py +34 -3
  295. scipy/optimize/_numdiff.py +288 -110
  296. scipy/optimize/_optimize.py +86 -48
  297. scipy/optimize/_pava_pybind.cpython-313-aarch64-linux-musl.so +0 -0
  298. scipy/optimize/_remove_redundancy.py +5 -5
  299. scipy/optimize/_root_scalar.py +1 -1
  300. scipy/optimize/_shgo.py +6 -0
  301. scipy/optimize/_shgo_lib/_complex.py +1 -1
  302. scipy/optimize/_slsqp_py.py +216 -124
  303. scipy/optimize/_slsqplib.cpython-313-aarch64-linux-musl.so +0 -0
  304. scipy/optimize/_spectral.py +1 -1
  305. scipy/optimize/_tnc.py +8 -1
  306. scipy/optimize/_trlib/_trlib.cpython-313-aarch64-linux-musl.so +0 -0
  307. scipy/optimize/_trustregion.py +20 -6
  308. scipy/optimize/_trustregion_constr/canonical_constraint.py +7 -7
  309. scipy/optimize/_trustregion_constr/equality_constrained_sqp.py +1 -1
  310. scipy/optimize/_trustregion_constr/minimize_trustregion_constr.py +11 -3
  311. scipy/optimize/_trustregion_constr/projections.py +12 -8
  312. scipy/optimize/_trustregion_constr/qp_subproblem.py +9 -9
  313. scipy/optimize/_trustregion_constr/tests/test_projections.py +7 -7
  314. scipy/optimize/_trustregion_constr/tests/test_qp_subproblem.py +77 -77
  315. scipy/optimize/_trustregion_constr/tr_interior_point.py +5 -5
  316. scipy/optimize/_trustregion_exact.py +0 -1
  317. scipy/optimize/_zeros.cpython-313-aarch64-linux-musl.so +0 -0
  318. scipy/optimize/_zeros_py.py +97 -17
  319. scipy/optimize/cython_optimize/_zeros.cpython-313-aarch64-linux-musl.so +0 -0
  320. scipy/optimize/slsqp.py +0 -1
  321. scipy/optimize/tests/test__basinhopping.py +1 -1
  322. scipy/optimize/tests/test__differential_evolution.py +4 -4
  323. scipy/optimize/tests/test__linprog_clean_inputs.py +5 -3
  324. scipy/optimize/tests/test__numdiff.py +66 -22
  325. scipy/optimize/tests/test__remove_redundancy.py +2 -2
  326. scipy/optimize/tests/test__shgo.py +9 -1
  327. scipy/optimize/tests/test_bracket.py +36 -46
  328. scipy/optimize/tests/test_chandrupatla.py +133 -135
  329. scipy/optimize/tests/test_cobyla.py +74 -45
  330. scipy/optimize/tests/test_constraints.py +1 -1
  331. scipy/optimize/tests/test_differentiable_functions.py +226 -6
  332. scipy/optimize/tests/test_lbfgsb_hessinv.py +22 -0
  333. scipy/optimize/tests/test_least_squares.py +125 -13
  334. scipy/optimize/tests/test_linear_assignment.py +3 -3
  335. scipy/optimize/tests/test_linprog.py +3 -3
  336. scipy/optimize/tests/test_lsq_linear.py +6 -6
  337. scipy/optimize/tests/test_minimize_constrained.py +2 -2
  338. scipy/optimize/tests/test_minpack.py +4 -4
  339. scipy/optimize/tests/test_nnls.py +43 -3
  340. scipy/optimize/tests/test_nonlin.py +36 -0
  341. scipy/optimize/tests/test_optimize.py +98 -20
  342. scipy/optimize/tests/test_slsqp.py +36 -4
  343. scipy/optimize/tests/test_zeros.py +34 -1
  344. scipy/signal/__init__.py +12 -23
  345. scipy/signal/_delegators.py +568 -0
  346. scipy/signal/_filter_design.py +459 -241
  347. scipy/signal/_fir_filter_design.py +262 -90
  348. scipy/signal/_lti_conversion.py +3 -2
  349. scipy/signal/_ltisys.py +118 -91
  350. scipy/signal/_max_len_seq_inner.cpython-313-aarch64-linux-musl.so +0 -0
  351. scipy/signal/_peak_finding_utils.cpython-313-aarch64-linux-musl.so +0 -0
  352. scipy/signal/_polyutils.py +172 -0
  353. scipy/signal/_short_time_fft.py +519 -70
  354. scipy/signal/_signal_api.py +30 -0
  355. scipy/signal/_signaltools.py +719 -399
  356. scipy/signal/_sigtools.cpython-313-aarch64-linux-musl.so +0 -0
  357. scipy/signal/_sosfilt.cpython-313-aarch64-linux-musl.so +0 -0
  358. scipy/signal/_spectral_py.py +230 -50
  359. scipy/signal/_spline.cpython-313-aarch64-linux-musl.so +0 -0
  360. scipy/signal/_spline_filters.py +108 -68
  361. scipy/signal/_support_alternative_backends.py +73 -0
  362. scipy/signal/_upfirdn.py +4 -1
  363. scipy/signal/_upfirdn_apply.cpython-313-aarch64-linux-musl.so +0 -0
  364. scipy/signal/_waveforms.py +2 -11
  365. scipy/signal/_wavelets.py +1 -1
  366. scipy/signal/fir_filter_design.py +1 -0
  367. scipy/signal/spline.py +4 -11
  368. scipy/signal/tests/_scipy_spectral_test_shim.py +2 -171
  369. scipy/signal/tests/test_bsplines.py +114 -79
  370. scipy/signal/tests/test_cont2discrete.py +9 -2
  371. scipy/signal/tests/test_filter_design.py +721 -481
  372. scipy/signal/tests/test_fir_filter_design.py +332 -140
  373. scipy/signal/tests/test_savitzky_golay.py +4 -3
  374. scipy/signal/tests/test_short_time_fft.py +221 -3
  375. scipy/signal/tests/test_signaltools.py +2145 -1349
  376. scipy/signal/tests/test_spectral.py +50 -6
  377. scipy/signal/tests/test_splines.py +161 -96
  378. scipy/signal/tests/test_upfirdn.py +84 -50
  379. scipy/signal/tests/test_waveforms.py +20 -0
  380. scipy/signal/tests/test_windows.py +607 -466
  381. scipy/signal/windows/_windows.py +287 -148
  382. scipy/sparse/__init__.py +23 -4
  383. scipy/sparse/_base.py +270 -108
  384. scipy/sparse/_bsr.py +7 -4
  385. scipy/sparse/_compressed.py +59 -231
  386. scipy/sparse/_construct.py +90 -38
  387. scipy/sparse/_coo.py +115 -181
  388. scipy/sparse/_csc.py +4 -4
  389. scipy/sparse/_csparsetools.cpython-313-aarch64-linux-musl.so +0 -0
  390. scipy/sparse/_csr.py +2 -2
  391. scipy/sparse/_data.py +48 -48
  392. scipy/sparse/_dia.py +105 -18
  393. scipy/sparse/_dok.py +0 -23
  394. scipy/sparse/_index.py +4 -4
  395. scipy/sparse/_matrix.py +23 -0
  396. scipy/sparse/_sparsetools.cpython-313-aarch64-linux-musl.so +0 -0
  397. scipy/sparse/_sputils.py +37 -22
  398. scipy/sparse/base.py +0 -9
  399. scipy/sparse/bsr.py +0 -14
  400. scipy/sparse/compressed.py +0 -23
  401. scipy/sparse/construct.py +0 -6
  402. scipy/sparse/coo.py +0 -14
  403. scipy/sparse/csc.py +0 -3
  404. scipy/sparse/csgraph/_flow.cpython-313-aarch64-linux-musl.so +0 -0
  405. scipy/sparse/csgraph/_matching.cpython-313-aarch64-linux-musl.so +0 -0
  406. scipy/sparse/csgraph/_min_spanning_tree.cpython-313-aarch64-linux-musl.so +0 -0
  407. scipy/sparse/csgraph/_reordering.cpython-313-aarch64-linux-musl.so +0 -0
  408. scipy/sparse/csgraph/_shortest_path.cpython-313-aarch64-linux-musl.so +0 -0
  409. scipy/sparse/csgraph/_tools.cpython-313-aarch64-linux-musl.so +0 -0
  410. scipy/sparse/csgraph/_traversal.cpython-313-aarch64-linux-musl.so +0 -0
  411. scipy/sparse/csgraph/tests/test_matching.py +14 -2
  412. scipy/sparse/csgraph/tests/test_pydata_sparse.py +4 -1
  413. scipy/sparse/csgraph/tests/test_shortest_path.py +83 -27
  414. scipy/sparse/csr.py +0 -5
  415. scipy/sparse/data.py +1 -6
  416. scipy/sparse/dia.py +0 -7
  417. scipy/sparse/dok.py +0 -10
  418. scipy/sparse/linalg/_dsolve/_superlu.cpython-313-aarch64-linux-musl.so +0 -0
  419. scipy/sparse/linalg/_dsolve/linsolve.py +9 -0
  420. scipy/sparse/linalg/_dsolve/tests/test_linsolve.py +35 -28
  421. scipy/sparse/linalg/_eigen/arpack/_arpack.cpython-313-aarch64-linux-musl.so +0 -0
  422. scipy/sparse/linalg/_eigen/arpack/arpack.py +23 -17
  423. scipy/sparse/linalg/_eigen/lobpcg/lobpcg.py +6 -6
  424. scipy/sparse/linalg/_interface.py +17 -18
  425. scipy/sparse/linalg/_isolve/_gcrotmk.py +4 -4
  426. scipy/sparse/linalg/_isolve/iterative.py +51 -45
  427. scipy/sparse/linalg/_isolve/lgmres.py +6 -6
  428. scipy/sparse/linalg/_isolve/minres.py +5 -5
  429. scipy/sparse/linalg/_isolve/tfqmr.py +7 -7
  430. scipy/sparse/linalg/_isolve/utils.py +2 -8
  431. scipy/sparse/linalg/_matfuncs.py +1 -1
  432. scipy/sparse/linalg/_norm.py +1 -1
  433. scipy/sparse/linalg/_propack/_cpropack.cpython-313-aarch64-linux-musl.so +0 -0
  434. scipy/sparse/linalg/_propack/_dpropack.cpython-313-aarch64-linux-musl.so +0 -0
  435. scipy/sparse/linalg/_propack/_spropack.cpython-313-aarch64-linux-musl.so +0 -0
  436. scipy/sparse/linalg/_propack/_zpropack.cpython-313-aarch64-linux-musl.so +0 -0
  437. scipy/sparse/linalg/_special_sparse_arrays.py +39 -38
  438. scipy/sparse/linalg/tests/test_pydata_sparse.py +14 -0
  439. scipy/sparse/tests/test_arithmetic1d.py +5 -2
  440. scipy/sparse/tests/test_base.py +214 -42
  441. scipy/sparse/tests/test_common1d.py +7 -7
  442. scipy/sparse/tests/test_construct.py +1 -1
  443. scipy/sparse/tests/test_coo.py +272 -4
  444. scipy/sparse/tests/test_sparsetools.py +5 -0
  445. scipy/sparse/tests/test_sputils.py +36 -7
  446. scipy/spatial/_ckdtree.cpython-313-aarch64-linux-musl.so +0 -0
  447. scipy/spatial/_distance_pybind.cpython-313-aarch64-linux-musl.so +0 -0
  448. scipy/spatial/_distance_wrap.cpython-313-aarch64-linux-musl.so +0 -0
  449. scipy/spatial/_hausdorff.cpython-313-aarch64-linux-musl.so +0 -0
  450. scipy/spatial/_qhull.cpython-313-aarch64-linux-musl.so +0 -0
  451. scipy/spatial/_voronoi.cpython-313-aarch64-linux-musl.so +0 -0
  452. scipy/spatial/distance.py +49 -42
  453. scipy/spatial/tests/test_distance.py +15 -1
  454. scipy/spatial/tests/test_kdtree.py +1 -0
  455. scipy/spatial/tests/test_qhull.py +7 -2
  456. scipy/spatial/transform/__init__.py +5 -3
  457. scipy/spatial/transform/_rigid_transform.cpython-313-aarch64-linux-musl.so +0 -0
  458. scipy/spatial/transform/_rotation.cpython-313-aarch64-linux-musl.so +0 -0
  459. scipy/spatial/transform/tests/test_rigid_transform.py +1221 -0
  460. scipy/spatial/transform/tests/test_rotation.py +1213 -832
  461. scipy/spatial/transform/tests/test_rotation_groups.py +3 -3
  462. scipy/spatial/transform/tests/test_rotation_spline.py +29 -8
  463. scipy/special/__init__.py +1 -47
  464. scipy/special/_add_newdocs.py +34 -772
  465. scipy/special/_basic.py +22 -25
  466. scipy/special/_comb.cpython-313-aarch64-linux-musl.so +0 -0
  467. scipy/special/_ellip_harm_2.cpython-313-aarch64-linux-musl.so +0 -0
  468. scipy/special/_gufuncs.cpython-313-aarch64-linux-musl.so +0 -0
  469. scipy/special/_logsumexp.py +67 -58
  470. scipy/special/_orthogonal.pyi +1 -1
  471. scipy/special/_specfun.cpython-313-aarch64-linux-musl.so +0 -0
  472. scipy/special/_special_ufuncs.cpython-313-aarch64-linux-musl.so +0 -0
  473. scipy/special/_spherical_bessel.py +4 -4
  474. scipy/special/_support_alternative_backends.py +212 -119
  475. scipy/special/_test_internal.cpython-313-aarch64-linux-musl.so +0 -0
  476. scipy/special/_testutils.py +4 -4
  477. scipy/special/_ufuncs.cpython-313-aarch64-linux-musl.so +0 -0
  478. scipy/special/_ufuncs.pyi +1 -0
  479. scipy/special/_ufuncs.pyx +215 -1400
  480. scipy/special/_ufuncs_cxx.cpython-313-aarch64-linux-musl.so +0 -0
  481. scipy/special/_ufuncs_cxx.pxd +2 -15
  482. scipy/special/_ufuncs_cxx.pyx +5 -44
  483. scipy/special/_ufuncs_cxx_defs.h +2 -16
  484. scipy/special/_ufuncs_defs.h +0 -8
  485. scipy/special/cython_special.cpython-313-aarch64-linux-musl.so +0 -0
  486. scipy/special/cython_special.pxd +1 -1
  487. scipy/special/tests/_cython_examples/meson.build +10 -1
  488. scipy/special/tests/test_basic.py +153 -20
  489. scipy/special/tests/test_boost_ufuncs.py +3 -0
  490. scipy/special/tests/test_cdflib.py +35 -11
  491. scipy/special/tests/test_gammainc.py +16 -0
  492. scipy/special/tests/test_hyp2f1.py +2 -2
  493. scipy/special/tests/test_log1mexp.py +85 -0
  494. scipy/special/tests/test_logsumexp.py +206 -64
  495. scipy/special/tests/test_mpmath.py +1 -0
  496. scipy/special/tests/test_nan_inputs.py +1 -1
  497. scipy/special/tests/test_orthogonal.py +17 -18
  498. scipy/special/tests/test_sf_error.py +3 -2
  499. scipy/special/tests/test_sph_harm.py +6 -7
  500. scipy/special/tests/test_support_alternative_backends.py +211 -76
  501. scipy/stats/__init__.py +4 -1
  502. scipy/stats/_ansari_swilk_statistics.cpython-313-aarch64-linux-musl.so +0 -0
  503. scipy/stats/_axis_nan_policy.py +5 -12
  504. scipy/stats/_biasedurn.cpython-313-aarch64-linux-musl.so +0 -0
  505. scipy/stats/_continued_fraction.py +387 -0
  506. scipy/stats/_continuous_distns.py +277 -310
  507. scipy/stats/_correlation.py +1 -1
  508. scipy/stats/_covariance.py +6 -3
  509. scipy/stats/_discrete_distns.py +39 -32
  510. scipy/stats/_distn_infrastructure.py +39 -12
  511. scipy/stats/_distribution_infrastructure.py +920 -238
  512. scipy/stats/_entropy.py +9 -10
  513. scipy/{_lib → stats}/_finite_differences.py +1 -1
  514. scipy/stats/_hypotests.py +83 -50
  515. scipy/stats/_kde.py +53 -49
  516. scipy/stats/_ksstats.py +1 -1
  517. scipy/stats/_levy_stable/__init__.py +7 -15
  518. scipy/stats/_levy_stable/levyst.cpython-313-aarch64-linux-musl.so +0 -0
  519. scipy/stats/_morestats.py +118 -73
  520. scipy/stats/_mstats_basic.py +13 -17
  521. scipy/stats/_mstats_extras.py +8 -8
  522. scipy/stats/_multivariate.py +89 -113
  523. scipy/stats/_new_distributions.py +97 -20
  524. scipy/stats/_page_trend_test.py +12 -5
  525. scipy/stats/_probability_distribution.py +265 -43
  526. scipy/stats/_qmc.py +14 -9
  527. scipy/stats/_qmc_cy.cpython-313-aarch64-linux-musl.so +0 -0
  528. scipy/stats/_qmvnt.py +16 -95
  529. scipy/stats/_qmvnt_cy.cpython-313-aarch64-linux-musl.so +0 -0
  530. scipy/stats/_quantile.py +335 -0
  531. scipy/stats/_rcont/rcont.cpython-313-aarch64-linux-musl.so +0 -0
  532. scipy/stats/_resampling.py +5 -30
  533. scipy/stats/_sampling.py +1 -1
  534. scipy/stats/_sobol.cpython-313-aarch64-linux-musl.so +0 -0
  535. scipy/stats/_stats.cpython-313-aarch64-linux-musl.so +0 -0
  536. scipy/stats/_stats_mstats_common.py +21 -2
  537. scipy/stats/_stats_py.py +551 -477
  538. scipy/stats/_stats_pythran.cpython-313-aarch64-linux-musl.so +0 -0
  539. scipy/stats/_unuran/unuran_wrapper.cpython-313-aarch64-linux-musl.so +0 -0
  540. scipy/stats/_unuran/unuran_wrapper.pyi +2 -1
  541. scipy/stats/_variation.py +6 -8
  542. scipy/stats/_wilcoxon.py +13 -7
  543. scipy/stats/tests/common_tests.py +6 -4
  544. scipy/stats/tests/test_axis_nan_policy.py +62 -24
  545. scipy/stats/tests/test_continued_fraction.py +173 -0
  546. scipy/stats/tests/test_continuous.py +379 -60
  547. scipy/stats/tests/test_continuous_basic.py +18 -12
  548. scipy/stats/tests/test_discrete_basic.py +14 -8
  549. scipy/stats/tests/test_discrete_distns.py +16 -16
  550. scipy/stats/tests/test_distributions.py +95 -75
  551. scipy/stats/tests/test_entropy.py +40 -48
  552. scipy/stats/tests/test_fit.py +4 -3
  553. scipy/stats/tests/test_hypotests.py +153 -24
  554. scipy/stats/tests/test_kdeoth.py +109 -41
  555. scipy/stats/tests/test_marray.py +289 -0
  556. scipy/stats/tests/test_morestats.py +81 -49
  557. scipy/stats/tests/test_mstats_basic.py +3 -3
  558. scipy/stats/tests/test_multivariate.py +434 -83
  559. scipy/stats/tests/test_qmc.py +13 -10
  560. scipy/stats/tests/test_quantile.py +199 -0
  561. scipy/stats/tests/test_rank.py +119 -112
  562. scipy/stats/tests/test_resampling.py +47 -56
  563. scipy/stats/tests/test_sampling.py +9 -4
  564. scipy/stats/tests/test_stats.py +799 -939
  565. scipy/stats/tests/test_variation.py +8 -6
  566. scipy/version.py +2 -2
  567. {scipy-1.15.3.dist-info → scipy-1.16.0.dist-info}/LICENSE.txt +4 -4
  568. {scipy-1.15.3.dist-info → scipy-1.16.0.dist-info}/METADATA +11 -11
  569. {scipy-1.15.3.dist-info → scipy-1.16.0.dist-info}/RECORD +1284 -1291
  570. scipy.libs/libgcc_s-2d945d6c.so.1 +0 -0
  571. scipy.libs/libgfortran-67378ab2.so.5.0.0 +0 -0
  572. scipy.libs/{libstdc++-1b614e01.so.6.0.32 → libstdc++-85f2cd6d.so.6.0.33} +0 -0
  573. scipy/_lib/array_api_extra/_funcs.py +0 -484
  574. scipy/_lib/array_api_extra/_typing.py +0 -8
  575. scipy/interpolate/_bspl.cpython-313-aarch64-linux-musl.so +0 -0
  576. scipy/optimize/_cobyla.cpython-313-aarch64-linux-musl.so +0 -0
  577. scipy/optimize/_cython_nnls.cpython-313-aarch64-linux-musl.so +0 -0
  578. scipy/optimize/_slsqp.cpython-313-aarch64-linux-musl.so +0 -0
  579. scipy/spatial/qhull_src/COPYING.txt +0 -38
  580. scipy/special/libsf_error_state.so +0 -0
  581. scipy/special/tests/test_log_softmax.py +0 -109
  582. scipy/special/tests/test_xsf_cuda.py +0 -114
  583. scipy/special/xsf/binom.h +0 -89
  584. scipy/special/xsf/cdflib.h +0 -100
  585. scipy/special/xsf/cephes/airy.h +0 -307
  586. scipy/special/xsf/cephes/besselpoly.h +0 -51
  587. scipy/special/xsf/cephes/beta.h +0 -257
  588. scipy/special/xsf/cephes/cbrt.h +0 -131
  589. scipy/special/xsf/cephes/chbevl.h +0 -85
  590. scipy/special/xsf/cephes/chdtr.h +0 -193
  591. scipy/special/xsf/cephes/const.h +0 -87
  592. scipy/special/xsf/cephes/ellie.h +0 -293
  593. scipy/special/xsf/cephes/ellik.h +0 -251
  594. scipy/special/xsf/cephes/ellpe.h +0 -107
  595. scipy/special/xsf/cephes/ellpk.h +0 -117
  596. scipy/special/xsf/cephes/expn.h +0 -260
  597. scipy/special/xsf/cephes/gamma.h +0 -398
  598. scipy/special/xsf/cephes/hyp2f1.h +0 -596
  599. scipy/special/xsf/cephes/hyperg.h +0 -361
  600. scipy/special/xsf/cephes/i0.h +0 -149
  601. scipy/special/xsf/cephes/i1.h +0 -158
  602. scipy/special/xsf/cephes/igam.h +0 -421
  603. scipy/special/xsf/cephes/igam_asymp_coeff.h +0 -195
  604. scipy/special/xsf/cephes/igami.h +0 -313
  605. scipy/special/xsf/cephes/j0.h +0 -225
  606. scipy/special/xsf/cephes/j1.h +0 -198
  607. scipy/special/xsf/cephes/jv.h +0 -715
  608. scipy/special/xsf/cephes/k0.h +0 -164
  609. scipy/special/xsf/cephes/k1.h +0 -163
  610. scipy/special/xsf/cephes/kn.h +0 -243
  611. scipy/special/xsf/cephes/lanczos.h +0 -112
  612. scipy/special/xsf/cephes/ndtr.h +0 -275
  613. scipy/special/xsf/cephes/poch.h +0 -85
  614. scipy/special/xsf/cephes/polevl.h +0 -167
  615. scipy/special/xsf/cephes/psi.h +0 -194
  616. scipy/special/xsf/cephes/rgamma.h +0 -111
  617. scipy/special/xsf/cephes/scipy_iv.h +0 -811
  618. scipy/special/xsf/cephes/shichi.h +0 -248
  619. scipy/special/xsf/cephes/sici.h +0 -224
  620. scipy/special/xsf/cephes/sindg.h +0 -221
  621. scipy/special/xsf/cephes/tandg.h +0 -139
  622. scipy/special/xsf/cephes/trig.h +0 -58
  623. scipy/special/xsf/cephes/unity.h +0 -186
  624. scipy/special/xsf/cephes/zeta.h +0 -172
  625. scipy/special/xsf/config.h +0 -304
  626. scipy/special/xsf/digamma.h +0 -205
  627. scipy/special/xsf/error.h +0 -57
  628. scipy/special/xsf/evalpoly.h +0 -47
  629. scipy/special/xsf/expint.h +0 -266
  630. scipy/special/xsf/hyp2f1.h +0 -694
  631. scipy/special/xsf/iv_ratio.h +0 -173
  632. scipy/special/xsf/lambertw.h +0 -150
  633. scipy/special/xsf/loggamma.h +0 -163
  634. scipy/special/xsf/sici.h +0 -200
  635. scipy/special/xsf/tools.h +0 -427
  636. scipy/special/xsf/trig.h +0 -164
  637. scipy/special/xsf/wright_bessel.h +0 -843
  638. scipy/special/xsf/zlog1.h +0 -35
  639. scipy/stats/_mvn.cpython-313-aarch64-linux-musl.so +0 -0
  640. scipy.libs/libgcc_s-7393e603.so.1 +0 -0
  641. scipy.libs/libgfortran-eb933d8e.so.5.0.0 +0 -0
  642. {scipy-1.15.3.dist-info → scipy-1.16.0.dist-info}/WHEEL +0 -0
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._array_api import SCIPY_ARRAY_API, SCIPY_DEVICE
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,31 @@ except Exception:
29
34
 
30
35
 
31
36
  def pytest_configure(config):
37
+ """
38
+ Add pytest markers to avoid PytestUnknownMarkWarning
39
+
40
+ This needs to contain all markers that are SciPy-specific, as well as
41
+ dummy fallbacks for markers defined in optional test packages.
42
+
43
+ Note that we need both the registration here *and* in `pytest.ini`.
44
+ """
32
45
  config.addinivalue_line("markers",
33
46
  "slow: Tests that are very slow.")
34
47
  config.addinivalue_line("markers",
35
48
  "xslow: mark test as extremely slow (not run unless explicitly requested)")
36
49
  config.addinivalue_line("markers",
37
50
  "xfail_on_32bit: mark test as failing on 32-bit platforms")
51
+ config.addinivalue_line("markers",
52
+ "array_api_backends: test iterates on all array API backends")
53
+ config.addinivalue_line("markers",
54
+ ("skip_xp_backends(backends, reason=None, np_only=False, cpu_only=False, " +
55
+ "eager_only=False, exceptions=None): mark the desired skip configuration " +
56
+ "for the `skip_xp_backends` fixture"))
57
+ config.addinivalue_line("markers",
58
+ ("xfail_xp_backends(backends, reason=None, np_only=False, cpu_only=False, " +
59
+ "eager_only=False, exceptions=None): mark the desired xfail configuration " +
60
+ "for the `xfail_xp_backends` fixture"))
61
+
38
62
  try:
39
63
  import pytest_timeout # noqa:F401
40
64
  except Exception:
@@ -47,14 +71,7 @@ def pytest_configure(config):
47
71
  except Exception:
48
72
  config.addinivalue_line(
49
73
  "markers", 'fail_slow: mark a test for a non-default timeout failure')
50
- config.addinivalue_line("markers",
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.")
74
+
58
75
  if not PARALLEL_RUN_AVAILABLE:
59
76
  config.addinivalue_line(
60
77
  'markers',
@@ -141,17 +158,21 @@ if not PARALLEL_RUN_AVAILABLE:
141
158
 
142
159
 
143
160
  # Array API backend handling
161
+ xp_known_backends = {'numpy', 'array_api_strict', 'torch', 'cupy', 'jax.numpy',
162
+ 'dask.array'}
144
163
  xp_available_backends = {'numpy': np}
164
+ xp_skip_cpu_only_backends = set()
165
+ xp_skip_eager_only_backends = set()
145
166
 
146
- if SCIPY_ARRAY_API and isinstance(SCIPY_ARRAY_API, str):
167
+ if SCIPY_ARRAY_API:
147
168
  # fill the dict of backends with available libraries
148
169
  try:
149
170
  import array_api_strict
150
171
  xp_available_backends.update({'array_api_strict': array_api_strict})
151
- if _pep440.parse(array_api_strict.__version__) < _pep440.Version('2.0'):
152
- raise ImportError("array-api-strict must be >= version 2.0")
172
+ if _pep440.parse(array_api_strict.__version__) < _pep440.Version('2.3'):
173
+ raise ImportError("array-api-strict must be >= version 2.3")
153
174
  array_api_strict.set_array_api_strict_flags(
154
- api_version='2023.12'
175
+ api_version='2024.12'
155
176
  )
156
177
  except ImportError:
157
178
  pass
@@ -159,14 +180,35 @@ if SCIPY_ARRAY_API and isinstance(SCIPY_ARRAY_API, str):
159
180
  try:
160
181
  import torch # type: ignore[import-not-found]
161
182
  xp_available_backends.update({'torch': torch})
162
- # can use `mps` or `cpu`
163
183
  torch.set_default_device(SCIPY_DEVICE)
184
+ if SCIPY_DEVICE != "cpu":
185
+ xp_skip_cpu_only_backends.add('torch')
186
+
187
+ # default to float64 unless explicitly requested
188
+ default = os.getenv('SCIPY_DEFAULT_DTYPE', default='float64')
189
+ if default == 'float64':
190
+ torch.set_default_dtype(torch.float64)
191
+ elif default != "float32":
192
+ raise ValueError(
193
+ "SCIPY_DEFAULT_DTYPE env var, if set, can only be either 'float64' "
194
+ f"or 'float32'. Got '{default}' instead."
195
+ )
164
196
  except ImportError:
165
197
  pass
166
198
 
167
199
  try:
168
200
  import cupy # type: ignore[import-not-found]
201
+ # Note: cupy disregards SCIPY_DEVICE and always runs on cuda.
202
+ # It will fail to import if you don't have CUDA hardware and drivers.
169
203
  xp_available_backends.update({'cupy': cupy})
204
+ xp_skip_cpu_only_backends.add('cupy')
205
+
206
+ # this is annoying in CuPy 13.x
207
+ warnings.filterwarnings(
208
+ 'ignore', 'cupyx.jit.rawkernel is experimental', category=FutureWarning
209
+ )
210
+ from cupyx.scipy import signal
211
+ del signal
170
212
  except ImportError:
171
213
  pass
172
214
 
@@ -175,16 +217,35 @@ if SCIPY_ARRAY_API and isinstance(SCIPY_ARRAY_API, str):
175
217
  xp_available_backends.update({'jax.numpy': jax.numpy})
176
218
  jax.config.update("jax_enable_x64", True)
177
219
  jax.config.update("jax_default_device", jax.devices(SCIPY_DEVICE)[0])
220
+ if SCIPY_DEVICE != "cpu":
221
+ xp_skip_cpu_only_backends.add('jax.numpy')
222
+ # JAX can be eager or lazy (when wrapped in jax.jit). However it is
223
+ # recommended by upstream devs to assume it's always lazy.
224
+ xp_skip_eager_only_backends.add('jax.numpy')
225
+ except ImportError:
226
+ pass
227
+
228
+ try:
229
+ import dask.array as da
230
+ xp_available_backends.update({'dask.array': da})
231
+ # Dask can wrap around cupy. However, this is untested in scipy
232
+ # (and will almost surely not work as delegation will misbehave).
233
+
234
+ # Dask, strictly speaking, can be eager, in the sense that
235
+ # __array__, __bool__ etc. are implemented and do not raise.
236
+ # However, calling them triggers an extra computation of the whole graph
237
+ # until that point, which is highly destructive for performance.
238
+ xp_skip_eager_only_backends.add('dask.array')
178
239
  except ImportError:
179
240
  pass
180
241
 
181
242
  # by default, use all available backends
182
- if SCIPY_ARRAY_API.lower() not in ("1", "true"):
243
+ if (
244
+ isinstance(SCIPY_ARRAY_API, str)
245
+ and SCIPY_ARRAY_API.lower() not in ("1", "true", "all")
246
+ ):
183
247
  SCIPY_ARRAY_API_ = json.loads(SCIPY_ARRAY_API)
184
-
185
- if 'all' in SCIPY_ARRAY_API_:
186
- pass # same as True
187
- else:
248
+ if SCIPY_ARRAY_API_ != ['all']:
188
249
  # only select a subset of backend by filtering out the dict
189
250
  try:
190
251
  xp_available_backends = {
@@ -192,166 +253,220 @@ if SCIPY_ARRAY_API and isinstance(SCIPY_ARRAY_API, str):
192
253
  for backend in SCIPY_ARRAY_API_
193
254
  }
194
255
  except KeyError:
195
- msg = f"'--array-api-backend' must be in {xp_available_backends.keys()}"
256
+ msg = ("'--array-api-backend' must be in "
257
+ f"{list(xp_available_backends)}; got {SCIPY_ARRAY_API_}")
196
258
  raise ValueError(msg)
197
259
 
198
- if 'cupy' in xp_available_backends:
199
- SCIPY_DEVICE = 'cuda'
200
-
201
- array_api_compatible = pytest.mark.parametrize("xp", xp_available_backends.values())
202
-
203
- skip_xp_invalid_arg = pytest.mark.skipif(SCIPY_ARRAY_API,
204
- reason = ('Test involves masked arrays, object arrays, or other types '
205
- 'that are not valid input when `SCIPY_ARRAY_API` is used.'))
260
+ assert not set(xp_available_backends) - xp_known_backends
261
+ xp_skip_np_only_backends = set(xp_available_backends) - {"numpy"}
206
262
 
207
263
 
208
- def _backends_kwargs_from_request(request, skip_or_xfail):
209
- """A helper for {skip,xfail}_xp_backends"""
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_}")
264
+ @pytest.fixture(params=[
265
+ pytest.param(v, id=k, marks=pytest.mark.array_api_backends)
266
+ for k, v in xp_available_backends.items()
267
+ ])
268
+ def xp(request, monkeypatch):
269
+ """Run the test that uses this fixture on each available array API library.
216
270
 
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', [])
271
+ You can select all and only the tests that use the `xp` fixture by
272
+ passing `-m array_api_backends` to pytest.
229
273
 
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})
274
+ You can select where individual tests run through the `@skip_xp_backends`,
275
+ `@xfail_xp_backends`, and `@skip_xp_invalid_arg` pytest markers.
235
276
 
236
- return backends, kwargs
277
+ Please read: https://docs.scipy.org/doc/scipy/dev/api-dev/array_api.html#adding-tests
278
+ """
279
+ # Read all @pytest.marks.skip_xp_backends markers that decorate to the test,
280
+ # if any, and raise pytest.skip() if the current xp is in the list.
281
+ skip_or_xfail_xp_backends(request, "skip")
282
+ # Read all @pytest.marks.xfail_xp_backends markers that decorate the test,
283
+ # if any, and raise pytest.xfail() if the current xp is in the list.
284
+ skip_or_xfail_xp_backends(request, "xfail")
285
+
286
+ xp = request.param
287
+ # Potentially wrap namespace with array_api_compat
288
+ xp = array_namespace(xp.empty(0))
289
+
290
+ if SCIPY_ARRAY_API:
291
+ # If request.param==jax.numpy, wrap tested functions in jax.jit
292
+ patch_lazy_xp_functions(
293
+ xp=request.param, request=request, monkeypatch=monkeypatch
294
+ )
237
295
 
296
+ # Throughout all calls to assert_almost_equal, assert_array_almost_equal, and
297
+ # xp_assert_* functions, test that the array namespace is xp in both the
298
+ # expected and actual arrays. This is to detect the case where both arrays are
299
+ # erroneously just plain numpy while xp is something else.
300
+ with default_xp(xp):
301
+ yield xp
302
+ else:
303
+ yield xp
238
304
 
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
305
 
243
- Skip a decorated test for the provided backend, or skip a category of backends.
306
+ skip_xp_invalid_arg = pytest.mark.skipif(SCIPY_ARRAY_API,
307
+ reason = ('Test involves masked arrays, object arrays, or other types '
308
+ 'that are not valid input when `SCIPY_ARRAY_API` is used.'))
244
309
 
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
310
 
253
- backends, kwargs = _backends_kwargs_from_request(request, skip_or_xfail='skip')
254
- skip_or_xfail_xp_backends(xp, backends, kwargs, skip_or_xfail='skip')
311
+ def _backends_kwargs_from_request(request, skip_or_xfail):
312
+ """A helper for {skip,xfail}_xp_backends.
255
313
 
314
+ Return dict of {backend to skip/xfail: top reason to skip/xfail it}
315
+ """
316
+ markers = list(request.node.iter_markers(f'{skip_or_xfail}_xp_backends'))
317
+ reasons = {backend: [] for backend in xp_known_backends}
256
318
 
257
- @pytest.fixture
258
- def xfail_xp_backends(xp, request):
259
- """xfail_xp_backends(backend=None, reason=None, np_only=False, cpu_only=False, exceptions=None)
319
+ for marker in markers:
320
+ invalid_kwargs = set(marker.kwargs) - {
321
+ "cpu_only", "np_only", "eager_only", "reason", "exceptions"}
322
+ if invalid_kwargs:
323
+ raise TypeError(f"Invalid kwargs: {invalid_kwargs}")
324
+
325
+ exceptions = set(marker.kwargs.get('exceptions', []))
326
+ invalid_exceptions = exceptions - xp_known_backends
327
+ if (invalid_exceptions := list(exceptions - xp_known_backends)):
328
+ raise ValueError(f"Unknown backend(s): {invalid_exceptions}; "
329
+ f"must be a subset of {list(xp_known_backends)}")
330
+
331
+ if marker.kwargs.get('np_only', False):
332
+ reason = marker.kwargs.get("reason") or "do not run with non-NumPy backends"
333
+ for backend in xp_skip_np_only_backends - exceptions:
334
+ reasons[backend].append(reason)
335
+
336
+ elif marker.kwargs.get('cpu_only', False):
337
+ reason = marker.kwargs.get("reason") or (
338
+ "no array-agnostic implementation or delegation available "
339
+ "for this backend and device")
340
+ for backend in xp_skip_cpu_only_backends - exceptions:
341
+ reasons[backend].append(reason)
342
+
343
+ elif marker.kwargs.get('eager_only', False):
344
+ reason = marker.kwargs.get("reason") or (
345
+ "eager checks not executed on lazy backends")
346
+ for backend in xp_skip_eager_only_backends - exceptions:
347
+ reasons[backend].append(reason)
260
348
 
261
- xfail a decorated test for the provided backend, or xfail a category of backends.
349
+ # add backends, if any
350
+ if len(marker.args) == 1:
351
+ backend = marker.args[0]
352
+ if backend not in xp_known_backends:
353
+ raise ValueError(f"Unknown backend: {backend}; "
354
+ f"must be one of {list(xp_known_backends)}")
355
+ reason = marker.kwargs.get("reason") or (
356
+ f"do not run with array API backend: {backend}")
357
+ # reason overrides the ones from cpu_only, np_only, and eager_only.
358
+ # This is regardless of order of appearence of the markers.
359
+ reasons[backend].insert(0, reason)
360
+
361
+ for kwarg in ("cpu_only", "np_only", "eager_only", "exceptions"):
362
+ if kwarg in marker.kwargs:
363
+ raise ValueError(f"{kwarg} is mutually exclusive with {backend}")
364
+
365
+ elif len(marker.args) > 1:
366
+ raise ValueError(
367
+ f"Please specify only one backend per marker: {marker.args}"
368
+ )
369
+
370
+ return {backend: backend_reasons[0]
371
+ for backend, backend_reasons in reasons.items()
372
+ if backend_reasons}
373
+
374
+
375
+ def skip_or_xfail_xp_backends(request: pytest.FixtureRequest,
376
+ skip_or_xfail: Literal['skip', 'xfail']) -> None:
377
+ """
378
+ Helper of the `xp` fixture.
379
+ Skip or xfail based on the ``skip_xp_backends`` or ``xfail_xp_backends`` markers.
262
380
 
263
- See ``skip_or_xfail_backends`` docstring for details. Note that, contrary to
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')
381
+ See the "Support for the array API standard" docs page for usage examples.
272
382
 
383
+ Usage
384
+ -----
385
+ ::
386
+ skip_xp_backends = pytest.mark.skip_xp_backends
387
+ xfail_xp_backends = pytest.mark.xfail_xp_backends
388
+ ...
273
389
 
274
- def skip_or_xfail_xp_backends(xp, backends, kwargs, skip_or_xfail='skip'):
275
- """
276
- Skip based on the ``skip_xp_backends`` or ``xfail_xp_backends`` marker.
390
+ @skip_xp_backends(backend, *, reason=None)
391
+ @skip_xp_backends(*, cpu_only=True, exceptions=(), reason=None)
392
+ @skip_xp_backends(*, eager_only=True, exceptions=(), reason=None)
393
+ @skip_xp_backends(*, np_only=True, exceptions=(), reason=None)
277
394
 
278
- See the "Support for the array API standard" docs page for usage examples.
395
+ @xfail_xp_backends(backend, *, reason=None)
396
+ @xfail_xp_backends(*, cpu_only=True, exceptions=(), reason=None)
397
+ @xfail_xp_backends(*, eager_only=True, exceptions=(), reason=None)
398
+ @xfail_xp_backends(*, np_only=True, exceptions=(), reason=None)
279
399
 
280
400
  Parameters
281
401
  ----------
282
- backends : tuple
283
- Backends to skip/xfail, e.g. ``("array_api_strict", "torch")``.
284
- These are overriden when ``np_only`` is ``True``, and are not
285
- necessary to provide for non-CPU backends when ``cpu_only`` is ``True``.
286
- For a custom reason to apply, you should pass a dict ``{'reason': '...'}``
287
- to a keyword matching the name of the backend.
288
- reason : str, optional
289
- A reason for the skip/xfail in the case of ``np_only=True``.
290
- If unprovided, a default reason is used. Note that it is not possible
291
- to specify a custom reason with ``cpu_only``.
402
+ backend : str, optional
403
+ Backend to skip/xfail, e.g. ``"torch"``.
404
+ Mutually exclusive with ``cpu_only``, ``eager_only``, and ``np_only``.
405
+ cpu_only : bool, optional
406
+ When ``True``, the test is skipped/xfailed on non-CPU devices,
407
+ minus exceptions. Mutually exclusive with ``backend``.
408
+ eager_only : bool, optional
409
+ When ``True``, the test is skipped/xfailed for lazy backends, e.g. those
410
+ with major caveats when invoking ``__array__``, ``__bool__``, ``__float__``,
411
+ or ``__complex__``, minus exceptions. Mutually exclusive with ``backend``.
292
412
  np_only : bool, optional
293
413
  When ``True``, the test is skipped/xfailed for all backends other
294
- than the default NumPy backend. There is no need to provide
295
- any ``backends`` in this case. To specify a reason, pass a
296
- value to ``reason``. Default: ``False``.
297
- cpu_only : bool, optional
298
- When ``True``, the test is skipped/xfailed on non-CPU devices.
299
- There is no need to provide any ``backends`` in this case,
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``.
414
+ than the default NumPy backend and the exceptions.
415
+ Mutually exclusive with ``backend``. Implies ``cpu_only`` and ``eager_only``.
416
+ reason : str, optional
417
+ A reason for the skip/xfail. If omitted, a default reason is used.
418
+ exceptions : list[str], optional
419
+ A list of exceptions for use with ``cpu_only``, ``eager_only``, or ``np_only``.
304
420
  This should be provided when delegation is implemented for some,
305
421
  but not all, non-CPU/non-NumPy backends.
306
- skip_or_xfail : str
307
- ``'skip'`` to skip, ``'xfail'`` to xfail.
308
422
  """
309
- skip_or_xfail = getattr(pytest, 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)
423
+ if f"{skip_or_xfail}_xp_backends" not in request.keywords:
331
424
  return
332
- if cpu_only:
333
- reason = ("no array-agnostic implementation or delegation available "
334
- "for this backend and device")
335
- exceptions = [] if exceptions is None else exceptions
336
- if SCIPY_ARRAY_API and SCIPY_DEVICE != 'cpu':
337
- if xp.__name__ == 'cupy' and 'cupy' not in exceptions:
338
- skip_or_xfail(reason=reason)
339
- elif xp.__name__ == 'torch' and 'torch' not in exceptions:
340
- if 'cpu' not in xp.empty(0).device.type:
341
- skip_or_xfail(reason=reason)
342
- elif xp.__name__ == 'jax.numpy' and 'jax.numpy' not in exceptions:
343
- for d in xp.empty(0).devices():
344
- if 'cpu' not in d.device_kind:
345
- skip_or_xfail(reason=reason)
346
-
347
- if backends is not None:
348
- for i, backend in enumerate(backends):
349
- if xp.__name__ == backend:
350
- reason = kwargs[backend].get('reason')
351
- if not reason:
352
- reason = f"do not run with array API backend: {backend}"
353
-
354
- skip_or_xfail(reason=reason)
425
+
426
+ skip_xfail_reasons = _backends_kwargs_from_request(
427
+ request, skip_or_xfail=skip_or_xfail
428
+ )
429
+ xp = request.param
430
+ if xp.__name__ in skip_xfail_reasons:
431
+ reason = skip_xfail_reasons[xp.__name__]
432
+ assert reason # Default reason applied above
433
+ skip_or_xfail = getattr(pytest, skip_or_xfail)
434
+ skip_or_xfail(reason=reason)
435
+
436
+
437
+ @pytest.fixture
438
+ def devices(xp):
439
+ """Fixture that returns a list of all devices for the backend, plus None.
440
+ Used to test input->output device propagation.
441
+
442
+ Usage
443
+ -----
444
+ from scipy._lib._array_api import xp_device
445
+
446
+ def test_device(xp, devices):
447
+ for d in devices:
448
+ x = xp.asarray(..., device=d)
449
+ y = f(x)
450
+ assert xp_device(y) == xp_device(x)
451
+ """
452
+ if is_cupy(xp):
453
+ # CuPy does not support devices other than the current one
454
+ # data-apis/array-api-compat#293
455
+ pytest.xfail(reason="data-apis/array-api-compat#293")
456
+ if is_dask(xp):
457
+ # Skip dummy DASK_DEVICE from array-api-compat, which does not propagate
458
+ return ["cpu", None]
459
+ if is_jax(xp):
460
+ # The .device attribute is not accessible inside jax.jit; the consequence
461
+ # (downstream of array-api-compat hacks) is that a non-default device in
462
+ # input is not guaranteed to propagate to the output even if the scipy code
463
+ # states `device=xp_device(arg)`` in all array creation functions.
464
+ # While this issue is specific to jax.jit, it would be unnecessarily
465
+ # verbose to skip the test for each jit-capable function and run it for
466
+ # those that only support eager mode.
467
+ pytest.xfail(reason="jax-ml/jax#26000")
468
+
469
+ return xp.__array_namespace_info__().devices() + [None]
355
470
 
356
471
 
357
472
  # Following the approach of NumPy's conftest.py...
@@ -521,12 +636,25 @@ if HAVE_SCPDT:
521
636
  # equivalent to "pytest --ignore=path/to/file"
522
637
  "scipy/special/_precompute",
523
638
  "scipy/interpolate/_interpnd_info.py",
639
+ "scipy/interpolate/_rbfinterp_pythran.py",
640
+ "scipy/_build_utils/tempita.py",
524
641
  "scipy/_lib/array_api_compat",
525
642
  "scipy/_lib/highs",
526
643
  "scipy/_lib/unuran",
527
644
  "scipy/_lib/_gcutils.py",
528
645
  "scipy/_lib/doccer.py",
529
646
  "scipy/_lib/_uarray",
647
+ "scipy/linalg/_cython_signature_generator.py",
648
+ "scipy/linalg/_generate_pyx.py",
649
+ "scipy/linalg/_linalg_pythran.py",
650
+ "scipy/linalg/_matfuncs_sqrtm_triu.py",
651
+ "scipy/ndimage/utils/generate_label_testvectors.py",
652
+ "scipy/optimize/_group_columns.py",
653
+ "scipy/optimize/_max_len_seq_inner.py",
654
+ "scipy/signal/_max_len_seq_inner.py",
655
+ "scipy/sparse/_generate_sparsetools.py",
656
+ "scipy/special/_generate_pyx.py",
657
+ "scipy/stats/_stats_pythran.py",
530
658
  ]
531
659
 
532
660
  dt_config.pytest_extra_xfail = {
@@ -549,4 +677,7 @@ if HAVE_SCPDT:
549
677
  }
550
678
 
551
679
  dt_config.strict_check = True
680
+
681
+ # ignore Matplotlib's `ax.text`:
682
+ dt_config.stopwords.add('.text(')
552
683
  ############################################################################
@@ -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('%d %s' % (_cd.value('speed of light in vacuum'),
35
- _cd.unit('speed of light in vacuum')),
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