scipy 1.15.3__cp312-cp312-musllinux_1_2_aarch64.whl → 1.16.0rc2__cp312-cp312-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 (641) hide show
  1. scipy/__config__.py +10 -10
  2. scipy/__init__.py +3 -6
  3. scipy/_cyutility.cpython-312-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-312-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-312-aarch64-linux-musl.so +0 -0
  11. scipy/_lib/_sparse.py +41 -0
  12. scipy/_lib/_test_ccallback.cpython-312-aarch64-linux-musl.so +0 -0
  13. scipy/_lib/_test_deprecation_call.cpython-312-aarch64-linux-musl.so +0 -0
  14. scipy/_lib/_test_deprecation_def.cpython-312-aarch64-linux-musl.so +0 -0
  15. scipy/_lib/_testutils.py +6 -2
  16. scipy/_lib/_uarray/_uarray.cpython-312-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-312-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-312-aarch64-linux-musl.so +0 -0
  97. scipy/cluster/_optimal_leaf_ordering.cpython-312-aarch64-linux-musl.so +0 -0
  98. scipy/cluster/_vq.cpython-312-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 +263 -157
  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-312-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-312-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-312-aarch64-linux-musl.so +0 -0
  129. scipy/integrate/_lsoda.cpython-312-aarch64-linux-musl.so +0 -0
  130. scipy/integrate/_ode.py +9 -2
  131. scipy/integrate/_odepack.cpython-312-aarch64-linux-musl.so +0 -0
  132. scipy/integrate/_quad_vec.py +21 -29
  133. scipy/integrate/_quadpack.cpython-312-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-312-aarch64-linux-musl.so +0 -0
  139. scipy/integrate/_test_odeint_banded.cpython-312-aarch64-linux-musl.so +0 -0
  140. scipy/integrate/_vode.cpython-312-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-312-aarch64-linux-musl.so +0 -0
  151. scipy/interpolate/_dierckx.cpython-312-aarch64-linux-musl.so +0 -0
  152. scipy/interpolate/_fitpack.cpython-312-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-312-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-312-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-312-aarch64-linux-musl.so +0 -0
  165. scipy/interpolate/_rgi.py +31 -26
  166. scipy/interpolate/_rgi_cython.cpython-312-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-312-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-312-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-312-aarch64-linux-musl.so +0 -0
  187. scipy/io/matlab/_mio_utils.cpython-312-aarch64-linux-musl.so +0 -0
  188. scipy/io/matlab/_miobase.py +4 -1
  189. scipy/io/matlab/_streams.cpython-312-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-312-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-312-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-312-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-312-aarch64-linux-musl.so +0 -0
  210. scipy/linalg/_expm_frechet.py +4 -0
  211. scipy/linalg/_fblas.cpython-312-aarch64-linux-musl.so +0 -0
  212. scipy/linalg/_flapack.cpython-312-aarch64-linux-musl.so +0 -0
  213. scipy/linalg/_linalg_pythran.cpython-312-aarch64-linux-musl.so +0 -0
  214. scipy/linalg/_matfuncs.py +187 -4
  215. scipy/linalg/_matfuncs_expm.cpython-312-aarch64-linux-musl.so +0 -0
  216. scipy/linalg/_matfuncs_schur_sqrtm.cpython-312-aarch64-linux-musl.so +0 -0
  217. scipy/linalg/_matfuncs_sqrtm.py +1 -99
  218. scipy/linalg/_matfuncs_sqrtm_triu.cpython-312-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-312-aarch64-linux-musl.so +0 -0
  222. scipy/linalg/_solvers.py +7 -2
  223. scipy/linalg/_special_matrices.py +26 -36
  224. scipy/linalg/cython_blas.cpython-312-aarch64-linux-musl.so +0 -0
  225. scipy/linalg/cython_lapack.cpython-312-aarch64-linux-musl.so +0 -0
  226. scipy/linalg/lapack.py +22 -2
  227. scipy/linalg/tests/_cython_examples/meson.build +7 -0
  228. scipy/linalg/tests/test_basic.py +31 -16
  229. scipy/linalg/tests/test_batch.py +588 -0
  230. scipy/linalg/tests/test_cythonized_array_utils.py +0 -2
  231. scipy/linalg/tests/test_decomp.py +40 -3
  232. scipy/linalg/tests/test_decomp_cossin.py +14 -0
  233. scipy/linalg/tests/test_decomp_ldl.py +1 -1
  234. scipy/linalg/tests/test_lapack.py +115 -7
  235. scipy/linalg/tests/test_matfuncs.py +157 -102
  236. scipy/linalg/tests/test_procrustes.py +0 -7
  237. scipy/linalg/tests/test_solve_toeplitz.py +1 -1
  238. scipy/linalg/tests/test_special_matrices.py +1 -5
  239. scipy/ndimage/__init__.py +1 -0
  240. scipy/ndimage/_ctest.cpython-312-aarch64-linux-musl.so +0 -0
  241. scipy/ndimage/_cytest.cpython-312-aarch64-linux-musl.so +0 -0
  242. scipy/ndimage/_delegators.py +8 -2
  243. scipy/ndimage/_filters.py +453 -5
  244. scipy/ndimage/_interpolation.py +36 -6
  245. scipy/ndimage/_measurements.py +4 -2
  246. scipy/ndimage/_morphology.py +5 -0
  247. scipy/ndimage/_nd_image.cpython-312-aarch64-linux-musl.so +0 -0
  248. scipy/ndimage/_ni_docstrings.py +5 -1
  249. scipy/ndimage/_ni_label.cpython-312-aarch64-linux-musl.so +0 -0
  250. scipy/ndimage/_ni_support.py +1 -5
  251. scipy/ndimage/_rank_filter_1d.cpython-312-aarch64-linux-musl.so +0 -0
  252. scipy/ndimage/_support_alternative_backends.py +18 -6
  253. scipy/ndimage/tests/test_filters.py +370 -259
  254. scipy/ndimage/tests/test_fourier.py +7 -9
  255. scipy/ndimage/tests/test_interpolation.py +68 -61
  256. scipy/ndimage/tests/test_measurements.py +18 -35
  257. scipy/ndimage/tests/test_morphology.py +143 -131
  258. scipy/ndimage/tests/test_splines.py +1 -3
  259. scipy/odr/__odrpack.cpython-312-aarch64-linux-musl.so +0 -0
  260. scipy/optimize/_basinhopping.py +13 -7
  261. scipy/optimize/_bglu_dense.cpython-312-aarch64-linux-musl.so +0 -0
  262. scipy/optimize/_bracket.py +17 -24
  263. scipy/optimize/_chandrupatla.py +9 -10
  264. scipy/optimize/_cobyla_py.py +104 -123
  265. scipy/optimize/_constraints.py +14 -10
  266. scipy/optimize/_differentiable_functions.py +371 -230
  267. scipy/optimize/_differentialevolution.py +4 -3
  268. scipy/optimize/_direct.cpython-312-aarch64-linux-musl.so +0 -0
  269. scipy/optimize/_dual_annealing.py +1 -1
  270. scipy/optimize/_elementwise.py +1 -4
  271. scipy/optimize/_group_columns.cpython-312-aarch64-linux-musl.so +0 -0
  272. scipy/optimize/_highspy/_core.cpython-312-aarch64-linux-musl.so +0 -0
  273. scipy/optimize/_highspy/_highs_options.cpython-312-aarch64-linux-musl.so +0 -0
  274. scipy/optimize/_lbfgsb.cpython-312-aarch64-linux-musl.so +0 -0
  275. scipy/optimize/_lbfgsb_py.py +57 -16
  276. scipy/optimize/_linprog_doc.py +2 -2
  277. scipy/optimize/_linprog_highs.py +2 -2
  278. scipy/optimize/_linprog_ip.py +25 -10
  279. scipy/optimize/_linprog_util.py +14 -16
  280. scipy/optimize/_lsap.cpython-312-aarch64-linux-musl.so +0 -0
  281. scipy/optimize/_lsq/common.py +3 -3
  282. scipy/optimize/_lsq/dogbox.py +16 -2
  283. scipy/optimize/_lsq/givens_elimination.cpython-312-aarch64-linux-musl.so +0 -0
  284. scipy/optimize/_lsq/least_squares.py +198 -126
  285. scipy/optimize/_lsq/lsq_linear.py +6 -6
  286. scipy/optimize/_lsq/trf.py +35 -8
  287. scipy/optimize/_milp.py +3 -1
  288. scipy/optimize/_minimize.py +105 -36
  289. scipy/optimize/_minpack.cpython-312-aarch64-linux-musl.so +0 -0
  290. scipy/optimize/_minpack_py.py +21 -14
  291. scipy/optimize/_moduleTNC.cpython-312-aarch64-linux-musl.so +0 -0
  292. scipy/optimize/_nnls.py +20 -21
  293. scipy/optimize/_nonlin.py +34 -3
  294. scipy/optimize/_numdiff.py +288 -110
  295. scipy/optimize/_optimize.py +86 -48
  296. scipy/optimize/_pava_pybind.cpython-312-aarch64-linux-musl.so +0 -0
  297. scipy/optimize/_remove_redundancy.py +5 -5
  298. scipy/optimize/_root_scalar.py +1 -1
  299. scipy/optimize/_shgo.py +6 -0
  300. scipy/optimize/_shgo_lib/_complex.py +1 -1
  301. scipy/optimize/_slsqp_py.py +216 -124
  302. scipy/optimize/_slsqplib.cpython-312-aarch64-linux-musl.so +0 -0
  303. scipy/optimize/_spectral.py +1 -1
  304. scipy/optimize/_tnc.py +8 -1
  305. scipy/optimize/_trlib/_trlib.cpython-312-aarch64-linux-musl.so +0 -0
  306. scipy/optimize/_trustregion.py +20 -6
  307. scipy/optimize/_trustregion_constr/canonical_constraint.py +7 -7
  308. scipy/optimize/_trustregion_constr/equality_constrained_sqp.py +1 -1
  309. scipy/optimize/_trustregion_constr/minimize_trustregion_constr.py +11 -3
  310. scipy/optimize/_trustregion_constr/projections.py +12 -8
  311. scipy/optimize/_trustregion_constr/qp_subproblem.py +9 -9
  312. scipy/optimize/_trustregion_constr/tests/test_projections.py +7 -7
  313. scipy/optimize/_trustregion_constr/tests/test_qp_subproblem.py +77 -77
  314. scipy/optimize/_trustregion_constr/tr_interior_point.py +5 -5
  315. scipy/optimize/_trustregion_exact.py +0 -1
  316. scipy/optimize/_zeros.cpython-312-aarch64-linux-musl.so +0 -0
  317. scipy/optimize/_zeros_py.py +97 -17
  318. scipy/optimize/cython_optimize/_zeros.cpython-312-aarch64-linux-musl.so +0 -0
  319. scipy/optimize/slsqp.py +0 -1
  320. scipy/optimize/tests/test__basinhopping.py +1 -1
  321. scipy/optimize/tests/test__differential_evolution.py +4 -4
  322. scipy/optimize/tests/test__linprog_clean_inputs.py +5 -3
  323. scipy/optimize/tests/test__numdiff.py +66 -22
  324. scipy/optimize/tests/test__remove_redundancy.py +2 -2
  325. scipy/optimize/tests/test__shgo.py +9 -1
  326. scipy/optimize/tests/test_bracket.py +36 -46
  327. scipy/optimize/tests/test_chandrupatla.py +133 -135
  328. scipy/optimize/tests/test_cobyla.py +74 -45
  329. scipy/optimize/tests/test_constraints.py +1 -1
  330. scipy/optimize/tests/test_differentiable_functions.py +226 -6
  331. scipy/optimize/tests/test_lbfgsb_hessinv.py +22 -0
  332. scipy/optimize/tests/test_least_squares.py +125 -13
  333. scipy/optimize/tests/test_linear_assignment.py +3 -3
  334. scipy/optimize/tests/test_linprog.py +3 -3
  335. scipy/optimize/tests/test_lsq_linear.py +6 -6
  336. scipy/optimize/tests/test_minimize_constrained.py +2 -2
  337. scipy/optimize/tests/test_minpack.py +4 -4
  338. scipy/optimize/tests/test_nnls.py +43 -3
  339. scipy/optimize/tests/test_nonlin.py +36 -0
  340. scipy/optimize/tests/test_optimize.py +95 -17
  341. scipy/optimize/tests/test_slsqp.py +36 -4
  342. scipy/optimize/tests/test_zeros.py +34 -1
  343. scipy/signal/__init__.py +12 -23
  344. scipy/signal/_delegators.py +568 -0
  345. scipy/signal/_filter_design.py +459 -241
  346. scipy/signal/_fir_filter_design.py +262 -90
  347. scipy/signal/_lti_conversion.py +3 -2
  348. scipy/signal/_ltisys.py +118 -91
  349. scipy/signal/_max_len_seq_inner.cpython-312-aarch64-linux-musl.so +0 -0
  350. scipy/signal/_peak_finding_utils.cpython-312-aarch64-linux-musl.so +0 -0
  351. scipy/signal/_polyutils.py +172 -0
  352. scipy/signal/_short_time_fft.py +519 -70
  353. scipy/signal/_signal_api.py +30 -0
  354. scipy/signal/_signaltools.py +719 -399
  355. scipy/signal/_sigtools.cpython-312-aarch64-linux-musl.so +0 -0
  356. scipy/signal/_sosfilt.cpython-312-aarch64-linux-musl.so +0 -0
  357. scipy/signal/_spectral_py.py +230 -50
  358. scipy/signal/_spline.cpython-312-aarch64-linux-musl.so +0 -0
  359. scipy/signal/_spline_filters.py +108 -68
  360. scipy/signal/_support_alternative_backends.py +73 -0
  361. scipy/signal/_upfirdn.py +4 -1
  362. scipy/signal/_upfirdn_apply.cpython-312-aarch64-linux-musl.so +0 -0
  363. scipy/signal/_waveforms.py +2 -11
  364. scipy/signal/_wavelets.py +1 -1
  365. scipy/signal/fir_filter_design.py +1 -0
  366. scipy/signal/spline.py +4 -11
  367. scipy/signal/tests/_scipy_spectral_test_shim.py +2 -171
  368. scipy/signal/tests/test_bsplines.py +114 -79
  369. scipy/signal/tests/test_cont2discrete.py +9 -2
  370. scipy/signal/tests/test_filter_design.py +721 -481
  371. scipy/signal/tests/test_fir_filter_design.py +332 -140
  372. scipy/signal/tests/test_savitzky_golay.py +4 -3
  373. scipy/signal/tests/test_short_time_fft.py +221 -3
  374. scipy/signal/tests/test_signaltools.py +2144 -1348
  375. scipy/signal/tests/test_spectral.py +50 -6
  376. scipy/signal/tests/test_splines.py +161 -96
  377. scipy/signal/tests/test_upfirdn.py +84 -50
  378. scipy/signal/tests/test_waveforms.py +20 -0
  379. scipy/signal/tests/test_windows.py +607 -466
  380. scipy/signal/windows/_windows.py +287 -148
  381. scipy/sparse/__init__.py +23 -4
  382. scipy/sparse/_base.py +270 -108
  383. scipy/sparse/_bsr.py +7 -4
  384. scipy/sparse/_compressed.py +59 -231
  385. scipy/sparse/_construct.py +90 -38
  386. scipy/sparse/_coo.py +115 -181
  387. scipy/sparse/_csc.py +4 -4
  388. scipy/sparse/_csparsetools.cpython-312-aarch64-linux-musl.so +0 -0
  389. scipy/sparse/_csr.py +2 -2
  390. scipy/sparse/_data.py +48 -48
  391. scipy/sparse/_dia.py +105 -18
  392. scipy/sparse/_dok.py +0 -23
  393. scipy/sparse/_index.py +4 -4
  394. scipy/sparse/_matrix.py +23 -0
  395. scipy/sparse/_sparsetools.cpython-312-aarch64-linux-musl.so +0 -0
  396. scipy/sparse/_sputils.py +37 -22
  397. scipy/sparse/base.py +0 -9
  398. scipy/sparse/bsr.py +0 -14
  399. scipy/sparse/compressed.py +0 -23
  400. scipy/sparse/construct.py +0 -6
  401. scipy/sparse/coo.py +0 -14
  402. scipy/sparse/csc.py +0 -3
  403. scipy/sparse/csgraph/_flow.cpython-312-aarch64-linux-musl.so +0 -0
  404. scipy/sparse/csgraph/_matching.cpython-312-aarch64-linux-musl.so +0 -0
  405. scipy/sparse/csgraph/_min_spanning_tree.cpython-312-aarch64-linux-musl.so +0 -0
  406. scipy/sparse/csgraph/_reordering.cpython-312-aarch64-linux-musl.so +0 -0
  407. scipy/sparse/csgraph/_shortest_path.cpython-312-aarch64-linux-musl.so +0 -0
  408. scipy/sparse/csgraph/_tools.cpython-312-aarch64-linux-musl.so +0 -0
  409. scipy/sparse/csgraph/_traversal.cpython-312-aarch64-linux-musl.so +0 -0
  410. scipy/sparse/csgraph/tests/test_matching.py +14 -2
  411. scipy/sparse/csgraph/tests/test_pydata_sparse.py +4 -1
  412. scipy/sparse/csgraph/tests/test_shortest_path.py +83 -27
  413. scipy/sparse/csr.py +0 -5
  414. scipy/sparse/data.py +1 -6
  415. scipy/sparse/dia.py +0 -7
  416. scipy/sparse/dok.py +0 -10
  417. scipy/sparse/linalg/_dsolve/_superlu.cpython-312-aarch64-linux-musl.so +0 -0
  418. scipy/sparse/linalg/_dsolve/linsolve.py +9 -0
  419. scipy/sparse/linalg/_dsolve/tests/test_linsolve.py +35 -28
  420. scipy/sparse/linalg/_eigen/arpack/_arpack.cpython-312-aarch64-linux-musl.so +0 -0
  421. scipy/sparse/linalg/_eigen/arpack/arpack.py +23 -17
  422. scipy/sparse/linalg/_eigen/lobpcg/lobpcg.py +6 -6
  423. scipy/sparse/linalg/_interface.py +17 -18
  424. scipy/sparse/linalg/_isolve/_gcrotmk.py +4 -4
  425. scipy/sparse/linalg/_isolve/iterative.py +51 -45
  426. scipy/sparse/linalg/_isolve/lgmres.py +6 -6
  427. scipy/sparse/linalg/_isolve/minres.py +5 -5
  428. scipy/sparse/linalg/_isolve/tfqmr.py +7 -7
  429. scipy/sparse/linalg/_isolve/utils.py +2 -8
  430. scipy/sparse/linalg/_matfuncs.py +1 -1
  431. scipy/sparse/linalg/_norm.py +1 -1
  432. scipy/sparse/linalg/_propack/_cpropack.cpython-312-aarch64-linux-musl.so +0 -0
  433. scipy/sparse/linalg/_propack/_dpropack.cpython-312-aarch64-linux-musl.so +0 -0
  434. scipy/sparse/linalg/_propack/_spropack.cpython-312-aarch64-linux-musl.so +0 -0
  435. scipy/sparse/linalg/_propack/_zpropack.cpython-312-aarch64-linux-musl.so +0 -0
  436. scipy/sparse/linalg/_special_sparse_arrays.py +39 -38
  437. scipy/sparse/linalg/tests/test_pydata_sparse.py +14 -0
  438. scipy/sparse/tests/test_arithmetic1d.py +5 -2
  439. scipy/sparse/tests/test_base.py +214 -42
  440. scipy/sparse/tests/test_common1d.py +7 -7
  441. scipy/sparse/tests/test_construct.py +1 -1
  442. scipy/sparse/tests/test_coo.py +272 -4
  443. scipy/sparse/tests/test_sparsetools.py +5 -0
  444. scipy/sparse/tests/test_sputils.py +36 -7
  445. scipy/spatial/_ckdtree.cpython-312-aarch64-linux-musl.so +0 -0
  446. scipy/spatial/_distance_pybind.cpython-312-aarch64-linux-musl.so +0 -0
  447. scipy/spatial/_distance_wrap.cpython-312-aarch64-linux-musl.so +0 -0
  448. scipy/spatial/_hausdorff.cpython-312-aarch64-linux-musl.so +0 -0
  449. scipy/spatial/_qhull.cpython-312-aarch64-linux-musl.so +0 -0
  450. scipy/spatial/_voronoi.cpython-312-aarch64-linux-musl.so +0 -0
  451. scipy/spatial/distance.py +49 -42
  452. scipy/spatial/tests/test_distance.py +15 -1
  453. scipy/spatial/tests/test_kdtree.py +1 -0
  454. scipy/spatial/tests/test_qhull.py +7 -2
  455. scipy/spatial/transform/__init__.py +5 -3
  456. scipy/spatial/transform/_rigid_transform.cpython-312-aarch64-linux-musl.so +0 -0
  457. scipy/spatial/transform/_rotation.cpython-312-aarch64-linux-musl.so +0 -0
  458. scipy/spatial/transform/tests/test_rigid_transform.py +1221 -0
  459. scipy/spatial/transform/tests/test_rotation.py +1213 -832
  460. scipy/spatial/transform/tests/test_rotation_groups.py +3 -3
  461. scipy/spatial/transform/tests/test_rotation_spline.py +29 -8
  462. scipy/special/__init__.py +1 -47
  463. scipy/special/_add_newdocs.py +34 -772
  464. scipy/special/_basic.py +22 -25
  465. scipy/special/_comb.cpython-312-aarch64-linux-musl.so +0 -0
  466. scipy/special/_ellip_harm_2.cpython-312-aarch64-linux-musl.so +0 -0
  467. scipy/special/_gufuncs.cpython-312-aarch64-linux-musl.so +0 -0
  468. scipy/special/_logsumexp.py +67 -58
  469. scipy/special/_orthogonal.pyi +1 -1
  470. scipy/special/_specfun.cpython-312-aarch64-linux-musl.so +0 -0
  471. scipy/special/_special_ufuncs.cpython-312-aarch64-linux-musl.so +0 -0
  472. scipy/special/_spherical_bessel.py +4 -4
  473. scipy/special/_support_alternative_backends.py +212 -119
  474. scipy/special/_test_internal.cpython-312-aarch64-linux-musl.so +0 -0
  475. scipy/special/_testutils.py +4 -4
  476. scipy/special/_ufuncs.cpython-312-aarch64-linux-musl.so +0 -0
  477. scipy/special/_ufuncs.pyi +1 -0
  478. scipy/special/_ufuncs.pyx +215 -1400
  479. scipy/special/_ufuncs_cxx.cpython-312-aarch64-linux-musl.so +0 -0
  480. scipy/special/_ufuncs_cxx.pxd +2 -15
  481. scipy/special/_ufuncs_cxx.pyx +5 -44
  482. scipy/special/_ufuncs_cxx_defs.h +2 -16
  483. scipy/special/_ufuncs_defs.h +0 -8
  484. scipy/special/cython_special.cpython-312-aarch64-linux-musl.so +0 -0
  485. scipy/special/cython_special.pxd +1 -1
  486. scipy/special/tests/_cython_examples/meson.build +10 -1
  487. scipy/special/tests/test_basic.py +153 -20
  488. scipy/special/tests/test_boost_ufuncs.py +3 -0
  489. scipy/special/tests/test_cdflib.py +35 -11
  490. scipy/special/tests/test_gammainc.py +16 -0
  491. scipy/special/tests/test_hyp2f1.py +2 -2
  492. scipy/special/tests/test_log1mexp.py +85 -0
  493. scipy/special/tests/test_logsumexp.py +206 -64
  494. scipy/special/tests/test_mpmath.py +1 -0
  495. scipy/special/tests/test_nan_inputs.py +1 -1
  496. scipy/special/tests/test_orthogonal.py +17 -18
  497. scipy/special/tests/test_sf_error.py +3 -2
  498. scipy/special/tests/test_sph_harm.py +6 -7
  499. scipy/special/tests/test_support_alternative_backends.py +211 -76
  500. scipy/stats/__init__.py +4 -1
  501. scipy/stats/_ansari_swilk_statistics.cpython-312-aarch64-linux-musl.so +0 -0
  502. scipy/stats/_axis_nan_policy.py +5 -12
  503. scipy/stats/_biasedurn.cpython-312-aarch64-linux-musl.so +0 -0
  504. scipy/stats/_continued_fraction.py +387 -0
  505. scipy/stats/_continuous_distns.py +277 -310
  506. scipy/stats/_correlation.py +1 -1
  507. scipy/stats/_covariance.py +6 -3
  508. scipy/stats/_discrete_distns.py +39 -32
  509. scipy/stats/_distn_infrastructure.py +39 -12
  510. scipy/stats/_distribution_infrastructure.py +900 -238
  511. scipy/stats/_entropy.py +9 -10
  512. scipy/{_lib → stats}/_finite_differences.py +1 -1
  513. scipy/stats/_hypotests.py +83 -50
  514. scipy/stats/_kde.py +53 -49
  515. scipy/stats/_ksstats.py +1 -1
  516. scipy/stats/_levy_stable/__init__.py +7 -15
  517. scipy/stats/_levy_stable/levyst.cpython-312-aarch64-linux-musl.so +0 -0
  518. scipy/stats/_morestats.py +118 -73
  519. scipy/stats/_mstats_basic.py +13 -17
  520. scipy/stats/_mstats_extras.py +8 -8
  521. scipy/stats/_multivariate.py +89 -113
  522. scipy/stats/_new_distributions.py +97 -20
  523. scipy/stats/_page_trend_test.py +12 -5
  524. scipy/stats/_probability_distribution.py +265 -43
  525. scipy/stats/_qmc.py +14 -9
  526. scipy/stats/_qmc_cy.cpython-312-aarch64-linux-musl.so +0 -0
  527. scipy/stats/_qmvnt.py +16 -95
  528. scipy/stats/_qmvnt_cy.cpython-312-aarch64-linux-musl.so +0 -0
  529. scipy/stats/_quantile.py +335 -0
  530. scipy/stats/_rcont/rcont.cpython-312-aarch64-linux-musl.so +0 -0
  531. scipy/stats/_resampling.py +4 -29
  532. scipy/stats/_sampling.py +1 -1
  533. scipy/stats/_sobol.cpython-312-aarch64-linux-musl.so +0 -0
  534. scipy/stats/_stats.cpython-312-aarch64-linux-musl.so +0 -0
  535. scipy/stats/_stats_mstats_common.py +21 -2
  536. scipy/stats/_stats_py.py +550 -476
  537. scipy/stats/_stats_pythran.cpython-312-aarch64-linux-musl.so +0 -0
  538. scipy/stats/_unuran/unuran_wrapper.cpython-312-aarch64-linux-musl.so +0 -0
  539. scipy/stats/_unuran/unuran_wrapper.pyi +2 -1
  540. scipy/stats/_variation.py +6 -8
  541. scipy/stats/_wilcoxon.py +13 -7
  542. scipy/stats/tests/common_tests.py +6 -4
  543. scipy/stats/tests/test_axis_nan_policy.py +62 -24
  544. scipy/stats/tests/test_continued_fraction.py +173 -0
  545. scipy/stats/tests/test_continuous.py +379 -60
  546. scipy/stats/tests/test_continuous_basic.py +18 -12
  547. scipy/stats/tests/test_discrete_basic.py +14 -8
  548. scipy/stats/tests/test_discrete_distns.py +16 -16
  549. scipy/stats/tests/test_distributions.py +95 -75
  550. scipy/stats/tests/test_entropy.py +40 -48
  551. scipy/stats/tests/test_fit.py +4 -3
  552. scipy/stats/tests/test_hypotests.py +153 -24
  553. scipy/stats/tests/test_kdeoth.py +109 -41
  554. scipy/stats/tests/test_marray.py +289 -0
  555. scipy/stats/tests/test_morestats.py +79 -47
  556. scipy/stats/tests/test_mstats_basic.py +3 -3
  557. scipy/stats/tests/test_multivariate.py +434 -83
  558. scipy/stats/tests/test_qmc.py +13 -10
  559. scipy/stats/tests/test_quantile.py +199 -0
  560. scipy/stats/tests/test_rank.py +119 -112
  561. scipy/stats/tests/test_resampling.py +47 -56
  562. scipy/stats/tests/test_sampling.py +9 -4
  563. scipy/stats/tests/test_stats.py +799 -939
  564. scipy/stats/tests/test_variation.py +8 -6
  565. scipy/version.py +2 -2
  566. {scipy-1.15.3.dist-info → scipy-1.16.0rc2.dist-info}/LICENSE.txt +4 -4
  567. {scipy-1.15.3.dist-info → scipy-1.16.0rc2.dist-info}/METADATA +11 -11
  568. {scipy-1.15.3.dist-info → scipy-1.16.0rc2.dist-info}/RECORD +1262 -1269
  569. scipy.libs/libgcc_s-69c45f16.so.1 +0 -0
  570. scipy.libs/libgfortran-db0b6589.so.5.0.0 +0 -0
  571. scipy.libs/{libstdc++-1b614e01.so.6.0.32 → libstdc++-1f1a71be.so.6.0.33} +0 -0
  572. scipy/_lib/array_api_extra/_funcs.py +0 -484
  573. scipy/_lib/array_api_extra/_typing.py +0 -8
  574. scipy/interpolate/_bspl.cpython-312-aarch64-linux-musl.so +0 -0
  575. scipy/optimize/_cobyla.cpython-312-aarch64-linux-musl.so +0 -0
  576. scipy/optimize/_cython_nnls.cpython-312-aarch64-linux-musl.so +0 -0
  577. scipy/optimize/_slsqp.cpython-312-aarch64-linux-musl.so +0 -0
  578. scipy/spatial/qhull_src/COPYING.txt +0 -38
  579. scipy/special/libsf_error_state.so +0 -0
  580. scipy/special/tests/test_log_softmax.py +0 -109
  581. scipy/special/tests/test_xsf_cuda.py +0 -114
  582. scipy/special/xsf/binom.h +0 -89
  583. scipy/special/xsf/cdflib.h +0 -100
  584. scipy/special/xsf/cephes/airy.h +0 -307
  585. scipy/special/xsf/cephes/besselpoly.h +0 -51
  586. scipy/special/xsf/cephes/beta.h +0 -257
  587. scipy/special/xsf/cephes/cbrt.h +0 -131
  588. scipy/special/xsf/cephes/chbevl.h +0 -85
  589. scipy/special/xsf/cephes/chdtr.h +0 -193
  590. scipy/special/xsf/cephes/const.h +0 -87
  591. scipy/special/xsf/cephes/ellie.h +0 -293
  592. scipy/special/xsf/cephes/ellik.h +0 -251
  593. scipy/special/xsf/cephes/ellpe.h +0 -107
  594. scipy/special/xsf/cephes/ellpk.h +0 -117
  595. scipy/special/xsf/cephes/expn.h +0 -260
  596. scipy/special/xsf/cephes/gamma.h +0 -398
  597. scipy/special/xsf/cephes/hyp2f1.h +0 -596
  598. scipy/special/xsf/cephes/hyperg.h +0 -361
  599. scipy/special/xsf/cephes/i0.h +0 -149
  600. scipy/special/xsf/cephes/i1.h +0 -158
  601. scipy/special/xsf/cephes/igam.h +0 -421
  602. scipy/special/xsf/cephes/igam_asymp_coeff.h +0 -195
  603. scipy/special/xsf/cephes/igami.h +0 -313
  604. scipy/special/xsf/cephes/j0.h +0 -225
  605. scipy/special/xsf/cephes/j1.h +0 -198
  606. scipy/special/xsf/cephes/jv.h +0 -715
  607. scipy/special/xsf/cephes/k0.h +0 -164
  608. scipy/special/xsf/cephes/k1.h +0 -163
  609. scipy/special/xsf/cephes/kn.h +0 -243
  610. scipy/special/xsf/cephes/lanczos.h +0 -112
  611. scipy/special/xsf/cephes/ndtr.h +0 -275
  612. scipy/special/xsf/cephes/poch.h +0 -85
  613. scipy/special/xsf/cephes/polevl.h +0 -167
  614. scipy/special/xsf/cephes/psi.h +0 -194
  615. scipy/special/xsf/cephes/rgamma.h +0 -111
  616. scipy/special/xsf/cephes/scipy_iv.h +0 -811
  617. scipy/special/xsf/cephes/shichi.h +0 -248
  618. scipy/special/xsf/cephes/sici.h +0 -224
  619. scipy/special/xsf/cephes/sindg.h +0 -221
  620. scipy/special/xsf/cephes/tandg.h +0 -139
  621. scipy/special/xsf/cephes/trig.h +0 -58
  622. scipy/special/xsf/cephes/unity.h +0 -186
  623. scipy/special/xsf/cephes/zeta.h +0 -172
  624. scipy/special/xsf/config.h +0 -304
  625. scipy/special/xsf/digamma.h +0 -205
  626. scipy/special/xsf/error.h +0 -57
  627. scipy/special/xsf/evalpoly.h +0 -47
  628. scipy/special/xsf/expint.h +0 -266
  629. scipy/special/xsf/hyp2f1.h +0 -694
  630. scipy/special/xsf/iv_ratio.h +0 -173
  631. scipy/special/xsf/lambertw.h +0 -150
  632. scipy/special/xsf/loggamma.h +0 -163
  633. scipy/special/xsf/sici.h +0 -200
  634. scipy/special/xsf/tools.h +0 -427
  635. scipy/special/xsf/trig.h +0 -164
  636. scipy/special/xsf/wright_bessel.h +0 -843
  637. scipy/special/xsf/zlog1.h +0 -35
  638. scipy/stats/_mvn.cpython-312-aarch64-linux-musl.so +0 -0
  639. scipy.libs/libgcc_s-7393e603.so.1 +0 -0
  640. scipy.libs/libgfortran-eb933d8e.so.5.0.0 +0 -0
  641. {scipy-1.15.3.dist-info → scipy-1.16.0rc2.dist-info}/WHEEL +0 -0
@@ -0,0 +1,463 @@
1
+ """Update operations for read-only arrays."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import operator
6
+ from collections.abc import Callable
7
+ from enum import Enum
8
+ from types import ModuleType
9
+ from typing import TYPE_CHECKING, ClassVar, cast
10
+
11
+ from ._utils import _compat
12
+ from ._utils._compat import (
13
+ array_namespace,
14
+ is_dask_array,
15
+ is_jax_array,
16
+ is_torch_array,
17
+ is_writeable_array,
18
+ )
19
+ from ._utils._helpers import meta_namespace
20
+ from ._utils._typing import Array, SetIndex
21
+
22
+ if TYPE_CHECKING: # pragma: no cover
23
+ # TODO import from typing (requires Python >=3.11)
24
+ from typing_extensions import Self
25
+
26
+
27
+ class _AtOp(Enum):
28
+ """Operations for use in `xpx.at`."""
29
+
30
+ SET = "set"
31
+ ADD = "add"
32
+ SUBTRACT = "subtract"
33
+ MULTIPLY = "multiply"
34
+ DIVIDE = "divide"
35
+ POWER = "power"
36
+ MIN = "min"
37
+ MAX = "max"
38
+
39
+ # @override from Python 3.12
40
+ def __str__(self) -> str: # type: ignore[explicit-override] # pyright: ignore[reportImplicitOverride]
41
+ """
42
+ Return string representation (useful for pytest logs).
43
+
44
+ Returns
45
+ -------
46
+ str
47
+ The operation's name.
48
+ """
49
+ return self.value
50
+
51
+
52
+ class Undef(Enum):
53
+ """Sentinel for undefined values."""
54
+
55
+ UNDEF = 0
56
+
57
+
58
+ _undef = Undef.UNDEF
59
+
60
+
61
+ class at: # pylint: disable=invalid-name # numpydoc ignore=PR02
62
+ """
63
+ Update operations for read-only arrays.
64
+
65
+ This implements ``jax.numpy.ndarray.at`` for all writeable
66
+ backends (those that support ``__setitem__``) and routes
67
+ to the ``.at[]`` method for JAX arrays.
68
+
69
+ Parameters
70
+ ----------
71
+ x : array
72
+ Input array.
73
+ idx : index, optional
74
+ Only `array API standard compliant indices
75
+ <https://data-apis.org/array-api/latest/API_specification/indexing.html>`_
76
+ are supported.
77
+
78
+ You may use two alternate syntaxes::
79
+
80
+ >>> import array_api_extra as xpx
81
+ >>> xpx.at(x, idx).set(value) # or add(value), etc.
82
+ >>> xpx.at(x)[idx].set(value)
83
+
84
+ copy : bool, optional
85
+ None (default)
86
+ The array parameter *may* be modified in place if it is
87
+ possible and beneficial for performance.
88
+ You should not reuse it after calling this function.
89
+ True
90
+ Ensure that the inputs are not modified.
91
+ False
92
+ Ensure that the update operation writes back to the input.
93
+ Raise ``ValueError`` if a copy cannot be avoided.
94
+
95
+ xp : array_namespace, optional
96
+ The standard-compatible namespace for `x`. Default: infer.
97
+
98
+ Returns
99
+ -------
100
+ Updated input array.
101
+
102
+ Warnings
103
+ --------
104
+ (a) When you omit the ``copy`` parameter, you should never reuse the parameter
105
+ array later on; ideally, you should reassign it immediately::
106
+
107
+ >>> import array_api_extra as xpx
108
+ >>> x = xpx.at(x, 0).set(2)
109
+
110
+ The above best practice pattern ensures that the behaviour won't change depending
111
+ on whether ``x`` is writeable or not, as the original ``x`` object is dereferenced
112
+ as soon as ``xpx.at`` returns; this way there is no risk to accidentally update it
113
+ twice.
114
+
115
+ On the reverse, the anti-pattern below must be avoided, as it will result in
116
+ different behaviour on read-only versus writeable arrays::
117
+
118
+ >>> x = xp.asarray([0, 0, 0])
119
+ >>> y = xpx.at(x, 0).set(2)
120
+ >>> z = xpx.at(x, 1).set(3)
121
+
122
+ In the above example, both calls to ``xpx.at`` update ``x`` in place *if possible*.
123
+ This causes the behaviour to diverge depending on whether ``x`` is writeable or not:
124
+
125
+ - If ``x`` is writeable, then after the snippet above you'll have
126
+ ``x == y == z == [2, 3, 0]``
127
+ - If ``x`` is read-only, then you'll end up with
128
+ ``x == [0, 0, 0]``, ``y == [2, 0, 0]`` and ``z == [0, 3, 0]``.
129
+
130
+ The correct pattern to use if you want diverging outputs from the same input is
131
+ to enforce copies::
132
+
133
+ >>> x = xp.asarray([0, 0, 0])
134
+ >>> y = xpx.at(x, 0).set(2, copy=True) # Never updates x
135
+ >>> z = xpx.at(x, 1).set(3) # May or may not update x in place
136
+ >>> del x # avoid accidental reuse of x as we don't know its state anymore
137
+
138
+ (b) The array API standard does not support integer array indices.
139
+ The behaviour of update methods when the index is an array of integers is
140
+ undefined and will vary between backends; this is particularly true when the
141
+ index contains multiple occurrences of the same index, e.g.::
142
+
143
+ >>> import numpy as np
144
+ >>> import jax.numpy as jnp
145
+ >>> import array_api_extra as xpx
146
+ >>> xpx.at(np.asarray([123]), np.asarray([0, 0])).add(1)
147
+ array([124])
148
+ >>> xpx.at(jnp.asarray([123]), jnp.asarray([0, 0])).add(1)
149
+ Array([125], dtype=int32)
150
+
151
+ See Also
152
+ --------
153
+ jax.numpy.ndarray.at : Equivalent array method in JAX.
154
+
155
+ Notes
156
+ -----
157
+ `sparse <https://sparse.pydata.org/>`_, as well as read-only arrays from libraries
158
+ not explicitly covered by ``array-api-compat``, are not supported by update
159
+ methods.
160
+
161
+ Boolean masks are supported on Dask and jitted JAX arrays exclusively
162
+ when `idx` has the same shape as `x` and `y` is 0-dimensional.
163
+ Note that this support is not available in JAX's native
164
+ ``x.at[mask].set(y)``.
165
+
166
+ This pattern::
167
+
168
+ >>> mask = m(x)
169
+ >>> x[mask] = f(x[mask])
170
+
171
+ Can't be replaced by `at`, as it won't work on Dask and JAX inside jax.jit::
172
+
173
+ >>> mask = m(x)
174
+ >>> x = xpx.at(x, mask).set(f(x[mask]) # Crash on Dask and jax.jit
175
+
176
+ You should instead use::
177
+
178
+ >>> x = xp.where(m(x), f(x), x)
179
+
180
+ Examples
181
+ --------
182
+ Given either of these equivalent expressions::
183
+
184
+ >>> import array_api_extra as xpx
185
+ >>> x = xpx.at(x)[1].add(2)
186
+ >>> x = xpx.at(x, 1).add(2)
187
+
188
+ If x is a JAX array, they are the same as::
189
+
190
+ >>> x = x.at[1].add(2)
191
+
192
+ If x is a read-only NumPy array, they are the same as::
193
+
194
+ >>> x = x.copy()
195
+ >>> x[1] += 2
196
+
197
+ For other known backends, they are the same as::
198
+
199
+ >>> x[1] += 2
200
+ """
201
+
202
+ _x: Array
203
+ _idx: SetIndex | Undef
204
+ __slots__: ClassVar[tuple[str, ...]] = ("_idx", "_x")
205
+
206
+ def __init__(
207
+ self, x: Array, idx: SetIndex | Undef = _undef, /
208
+ ) -> None: # numpydoc ignore=GL08
209
+ self._x = x
210
+ self._idx = idx
211
+
212
+ def __getitem__(self, idx: SetIndex, /) -> Self: # numpydoc ignore=PR01,RT01
213
+ """
214
+ Allow for the alternate syntax ``at(x)[start:stop:step]``.
215
+
216
+ It looks prettier than ``at(x, slice(start, stop, step))``
217
+ and feels more intuitive coming from the JAX documentation.
218
+ """
219
+ if self._idx is not _undef:
220
+ msg = "Index has already been set"
221
+ raise ValueError(msg)
222
+ return type(self)(self._x, idx)
223
+
224
+ def _op(
225
+ self,
226
+ at_op: _AtOp,
227
+ in_place_op: Callable[[Array, Array | complex], Array] | None,
228
+ out_of_place_op: Callable[[Array, Array], Array] | None,
229
+ y: Array | complex,
230
+ /,
231
+ copy: bool | None,
232
+ xp: ModuleType | None,
233
+ ) -> Array:
234
+ """
235
+ Implement all update operations.
236
+
237
+ Parameters
238
+ ----------
239
+ at_op : _AtOp
240
+ Method of JAX's Array.at[].
241
+ in_place_op : Callable[[Array, Array | complex], Array] | None
242
+ In-place operation to apply on mutable backends::
243
+
244
+ x[idx] = in_place_op(x[idx], y)
245
+
246
+ If None::
247
+
248
+ x[idx] = y
249
+
250
+ out_of_place_op : Callable[[Array, Array], Array] | None
251
+ Out-of-place operation to apply when idx is a boolean mask and the backend
252
+ doesn't support in-place updates::
253
+
254
+ x = xp.where(idx, out_of_place_op(x, y), x)
255
+
256
+ If None::
257
+
258
+ x = xp.where(idx, y, x)
259
+
260
+ y : array or complex
261
+ Right-hand side of the operation.
262
+ copy : bool or None
263
+ Whether to copy the input array. See the class docstring for details.
264
+ xp : array_namespace, optional
265
+ The array namespace for the input array. Default: infer.
266
+
267
+ Returns
268
+ -------
269
+ Array
270
+ Updated `x`.
271
+ """
272
+ from ._funcs import apply_where # pylint: disable=cyclic-import
273
+
274
+ x, idx = self._x, self._idx
275
+ xp = array_namespace(x, y) if xp is None else xp
276
+
277
+ if isinstance(idx, Undef):
278
+ msg = (
279
+ "Index has not been set.\n"
280
+ "Usage: either\n"
281
+ " at(x, idx).set(value)\n"
282
+ "or\n"
283
+ " at(x)[idx].set(value)\n"
284
+ "(same for all other methods)."
285
+ )
286
+ raise ValueError(msg)
287
+
288
+ if copy not in (True, False, None):
289
+ msg = f"copy must be True, False, or None; got {copy!r}"
290
+ raise ValueError(msg)
291
+
292
+ writeable = None if copy else is_writeable_array(x)
293
+
294
+ # JAX inside jax.jit doesn't support in-place updates with boolean
295
+ # masks; Dask exclusively supports __setitem__ but not iops.
296
+ # We can handle the common special case of 0-dimensional y
297
+ # with where(idx, y, x) instead.
298
+ if (
299
+ (is_dask_array(idx) or is_jax_array(idx))
300
+ and idx.dtype == xp.bool
301
+ and idx.shape == x.shape
302
+ ):
303
+ y_xp = xp.asarray(y, dtype=x.dtype, device=_compat.device(x))
304
+ if y_xp.ndim == 0:
305
+ if out_of_place_op: # add(), subtract(), ...
306
+ # suppress inf warnings on Dask
307
+ out = apply_where(
308
+ idx, (x, y_xp), out_of_place_op, fill_value=x, xp=xp
309
+ )
310
+ # Undo int->float promotion on JAX after _AtOp.DIVIDE
311
+ out = xp.astype(out, x.dtype, copy=False)
312
+ else: # set()
313
+ out = xp.where(idx, y_xp, x)
314
+
315
+ if copy is False:
316
+ x[()] = out
317
+ return x
318
+ return out
319
+
320
+ # else: this will work on eager JAX and crash on jax.jit and Dask
321
+
322
+ if copy or (copy is None and not writeable):
323
+ if is_jax_array(x):
324
+ # Use JAX's at[]
325
+ func = cast(
326
+ Callable[[Array | complex], Array],
327
+ getattr(x.at[idx], at_op.value), # type: ignore[attr-defined] # pyright: ignore[reportAttributeAccessIssue,reportUnknownArgumentType]
328
+ )
329
+ out = func(y)
330
+ # Undo int->float promotion on JAX after _AtOp.DIVIDE
331
+ return xp.astype(out, x.dtype, copy=False)
332
+
333
+ # Emulate at[] behaviour for non-JAX arrays
334
+ # with a copy followed by an update
335
+
336
+ x = xp.asarray(x, copy=True)
337
+ # A copy of a read-only numpy array is writeable
338
+ # Note: this assumes that a copy of a writeable array is writeable
339
+ assert not writeable
340
+ writeable = None
341
+
342
+ if writeable is None:
343
+ writeable = is_writeable_array(x)
344
+ if not writeable:
345
+ # sparse crashes here
346
+ msg = f"Can't update read-only array {x}"
347
+ raise ValueError(msg)
348
+
349
+ # Work around bug in PyTorch where __setitem__ doesn't
350
+ # always support mismatched dtypes
351
+ # https://github.com/pytorch/pytorch/issues/150017
352
+ if is_torch_array(y):
353
+ y = xp.astype(y, x.dtype, copy=False)
354
+
355
+ # Backends without boolean indexing (other than JAX) crash here
356
+ if in_place_op: # add(), subtract(), ...
357
+ x[idx] = in_place_op(x[idx], y)
358
+ else: # set()
359
+ x[idx] = y
360
+ return x
361
+
362
+ def set(
363
+ self,
364
+ y: Array | complex,
365
+ /,
366
+ copy: bool | None = None,
367
+ xp: ModuleType | None = None,
368
+ ) -> Array: # numpydoc ignore=PR01,RT01
369
+ """Apply ``x[idx] = y`` and return the update array."""
370
+ return self._op(_AtOp.SET, None, None, y, copy=copy, xp=xp)
371
+
372
+ def add(
373
+ self,
374
+ y: Array | complex,
375
+ /,
376
+ copy: bool | None = None,
377
+ xp: ModuleType | None = None,
378
+ ) -> Array: # numpydoc ignore=PR01,RT01
379
+ """Apply ``x[idx] += y`` and return the updated array."""
380
+
381
+ # Note for this and all other methods based on _iop:
382
+ # operator.iadd and operator.add subtly differ in behaviour, as
383
+ # only iadd will trigger exceptions when y has an incompatible dtype.
384
+ return self._op(_AtOp.ADD, operator.iadd, operator.add, y, copy=copy, xp=xp)
385
+
386
+ def subtract(
387
+ self,
388
+ y: Array | complex,
389
+ /,
390
+ copy: bool | None = None,
391
+ xp: ModuleType | None = None,
392
+ ) -> Array: # numpydoc ignore=PR01,RT01
393
+ """Apply ``x[idx] -= y`` and return the updated array."""
394
+ return self._op(
395
+ _AtOp.SUBTRACT, operator.isub, operator.sub, y, copy=copy, xp=xp
396
+ )
397
+
398
+ def multiply(
399
+ self,
400
+ y: Array | complex,
401
+ /,
402
+ copy: bool | None = None,
403
+ xp: ModuleType | None = None,
404
+ ) -> Array: # numpydoc ignore=PR01,RT01
405
+ """Apply ``x[idx] *= y`` and return the updated array."""
406
+ return self._op(
407
+ _AtOp.MULTIPLY, operator.imul, operator.mul, y, copy=copy, xp=xp
408
+ )
409
+
410
+ def divide(
411
+ self,
412
+ y: Array | complex,
413
+ /,
414
+ copy: bool | None = None,
415
+ xp: ModuleType | None = None,
416
+ ) -> Array: # numpydoc ignore=PR01,RT01
417
+ """Apply ``x[idx] /= y`` and return the updated array."""
418
+ return self._op(
419
+ _AtOp.DIVIDE, operator.itruediv, operator.truediv, y, copy=copy, xp=xp
420
+ )
421
+
422
+ def power(
423
+ self,
424
+ y: Array | complex,
425
+ /,
426
+ copy: bool | None = None,
427
+ xp: ModuleType | None = None,
428
+ ) -> Array: # numpydoc ignore=PR01,RT01
429
+ """Apply ``x[idx] **= y`` and return the updated array."""
430
+ return self._op(_AtOp.POWER, operator.ipow, operator.pow, y, copy=copy, xp=xp)
431
+
432
+ def min(
433
+ self,
434
+ y: Array | complex,
435
+ /,
436
+ copy: bool | None = None,
437
+ xp: ModuleType | None = None,
438
+ ) -> Array: # numpydoc ignore=PR01,RT01
439
+ """Apply ``x[idx] = minimum(x[idx], y)`` and return the updated array."""
440
+ # On Dask, this function runs on the chunks, so we need to determine the
441
+ # namespace that Dask is wrapping.
442
+ # Note that da.minimum _incidentally_ works on NumPy, CuPy, and sparse
443
+ # thanks to all these meta-namespaces implementing the __array_ufunc__
444
+ # interface, but there's no guarantee that it will work for other
445
+ # wrapped libraries in the future.
446
+ xp = array_namespace(self._x) if xp is None else xp
447
+ mxp = meta_namespace(self._x, xp=xp)
448
+ y = xp.asarray(y)
449
+ return self._op(_AtOp.MIN, mxp.minimum, mxp.minimum, y, copy=copy, xp=xp)
450
+
451
+ def max(
452
+ self,
453
+ y: Array | complex,
454
+ /,
455
+ copy: bool | None = None,
456
+ xp: ModuleType | None = None,
457
+ ) -> Array: # numpydoc ignore=PR01,RT01
458
+ """Apply ``x[idx] = maximum(x[idx], y)`` and return the updated array."""
459
+ # See note on min()
460
+ xp = array_namespace(self._x) if xp is None else xp
461
+ mxp = meta_namespace(self._x, xp=xp)
462
+ y = xp.asarray(y)
463
+ return self._op(_AtOp.MAX, mxp.maximum, mxp.maximum, y, copy=copy, xp=xp)
@@ -0,0 +1,46 @@
1
+ """Backends against which array-api-extra runs its tests."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from enum import Enum
6
+
7
+ __all__ = ["Backend"]
8
+
9
+
10
+ class Backend(Enum): # numpydoc ignore=PR02
11
+ """
12
+ All array library backends explicitly tested by array-api-extra.
13
+
14
+ Parameters
15
+ ----------
16
+ value : str
17
+ Tag of the backend's module, in the format ``<namespace>[:<extra tag>]``.
18
+ """
19
+
20
+ # Use :<tag> to prevent Enum from deduplicating items with the same value
21
+ ARRAY_API_STRICT = "array_api_strict"
22
+ ARRAY_API_STRICTEST = "array_api_strict:strictest"
23
+ NUMPY = "numpy"
24
+ NUMPY_READONLY = "numpy:readonly"
25
+ CUPY = "cupy"
26
+ TORCH = "torch"
27
+ TORCH_GPU = "torch:gpu"
28
+ DASK = "dask.array"
29
+ SPARSE = "sparse"
30
+ JAX = "jax.numpy"
31
+ JAX_GPU = "jax.numpy:gpu"
32
+
33
+ def __str__(self) -> str: # type: ignore[explicit-override] # pyright: ignore[reportImplicitOverride] # numpydoc ignore=RT01
34
+ """Pretty-print parameterized test names."""
35
+ return (
36
+ self.name.lower().replace("_gpu", ":gpu").replace("_readonly", ":readonly")
37
+ )
38
+
39
+ @property
40
+ def modname(self) -> str: # numpydoc ignore=RT01
41
+ """Module name to be imported."""
42
+ return self.value.split(":")[0]
43
+
44
+ def like(self, *others: Backend) -> bool: # numpydoc ignore=PR01,RT01
45
+ """Check if this backend uses the same module as others."""
46
+ return any(self.modname == other.modname for other in others)