scipy 1.15.2__cp313-cp313-macosx_12_0_arm64.whl → 1.16.0rc1__cp313-cp313-macosx_12_0_arm64.whl

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