scipy 1.15.3__cp312-cp312-macosx_12_0_arm64.whl → 1.16.0__cp312-cp312-macosx_12_0_arm64.whl

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