scipy 1.15.3__cp313-cp313t-macosx_14_0_arm64.whl → 1.16.0rc2__cp313-cp313t-macosx_14_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (627) hide show
  1. scipy/__config__.py +3 -3
  2. scipy/__init__.py +3 -6
  3. scipy/_cyutility.cpython-313t-darwin.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-313t-darwin.so +0 -0
  8. scipy/_lib/_docscrape.py +1 -1
  9. scipy/_lib/_elementwise_iterative_method.py +15 -26
  10. scipy/_lib/_sparse.py +41 -0
  11. scipy/_lib/_test_deprecation_call.cpython-313t-darwin.so +0 -0
  12. scipy/_lib/_testutils.py +6 -2
  13. scipy/_lib/_util.py +222 -125
  14. scipy/_lib/array_api_compat/__init__.py +4 -4
  15. scipy/_lib/array_api_compat/_internal.py +19 -6
  16. scipy/_lib/array_api_compat/common/__init__.py +1 -1
  17. scipy/_lib/array_api_compat/common/_aliases.py +365 -193
  18. scipy/_lib/array_api_compat/common/_fft.py +94 -64
  19. scipy/_lib/array_api_compat/common/_helpers.py +413 -180
  20. scipy/_lib/array_api_compat/common/_linalg.py +116 -40
  21. scipy/_lib/array_api_compat/common/_typing.py +179 -10
  22. scipy/_lib/array_api_compat/cupy/__init__.py +1 -4
  23. scipy/_lib/array_api_compat/cupy/_aliases.py +61 -41
  24. scipy/_lib/array_api_compat/cupy/_info.py +16 -6
  25. scipy/_lib/array_api_compat/cupy/_typing.py +24 -39
  26. scipy/_lib/array_api_compat/dask/array/__init__.py +6 -3
  27. scipy/_lib/array_api_compat/dask/array/_aliases.py +267 -108
  28. scipy/_lib/array_api_compat/dask/array/_info.py +105 -34
  29. scipy/_lib/array_api_compat/dask/array/fft.py +5 -8
  30. scipy/_lib/array_api_compat/dask/array/linalg.py +21 -22
  31. scipy/_lib/array_api_compat/numpy/__init__.py +13 -15
  32. scipy/_lib/array_api_compat/numpy/_aliases.py +98 -49
  33. scipy/_lib/array_api_compat/numpy/_info.py +36 -16
  34. scipy/_lib/array_api_compat/numpy/_typing.py +27 -43
  35. scipy/_lib/array_api_compat/numpy/fft.py +11 -5
  36. scipy/_lib/array_api_compat/numpy/linalg.py +75 -22
  37. scipy/_lib/array_api_compat/torch/__init__.py +3 -5
  38. scipy/_lib/array_api_compat/torch/_aliases.py +262 -159
  39. scipy/_lib/array_api_compat/torch/_info.py +27 -16
  40. scipy/_lib/array_api_compat/torch/_typing.py +3 -0
  41. scipy/_lib/array_api_compat/torch/fft.py +17 -18
  42. scipy/_lib/array_api_compat/torch/linalg.py +16 -16
  43. scipy/_lib/array_api_extra/__init__.py +26 -3
  44. scipy/_lib/array_api_extra/_delegation.py +171 -0
  45. scipy/_lib/array_api_extra/_lib/__init__.py +1 -0
  46. scipy/_lib/array_api_extra/_lib/_at.py +463 -0
  47. scipy/_lib/array_api_extra/_lib/_backends.py +46 -0
  48. scipy/_lib/array_api_extra/_lib/_funcs.py +937 -0
  49. scipy/_lib/array_api_extra/_lib/_lazy.py +357 -0
  50. scipy/_lib/array_api_extra/_lib/_testing.py +278 -0
  51. scipy/_lib/array_api_extra/_lib/_utils/__init__.py +1 -0
  52. scipy/_lib/array_api_extra/_lib/_utils/_compat.py +74 -0
  53. scipy/_lib/array_api_extra/_lib/_utils/_compat.pyi +45 -0
  54. scipy/_lib/array_api_extra/_lib/_utils/_helpers.py +559 -0
  55. scipy/_lib/array_api_extra/_lib/_utils/_typing.py +10 -0
  56. scipy/_lib/array_api_extra/_lib/_utils/_typing.pyi +105 -0
  57. scipy/_lib/array_api_extra/testing.py +359 -0
  58. scipy/_lib/decorator.py +2 -2
  59. scipy/_lib/doccer.py +1 -7
  60. scipy/_lib/messagestream.cpython-313t-darwin.so +0 -0
  61. scipy/_lib/pyprima/__init__.py +212 -0
  62. scipy/_lib/pyprima/cobyla/__init__.py +0 -0
  63. scipy/_lib/pyprima/cobyla/cobyla.py +559 -0
  64. scipy/_lib/pyprima/cobyla/cobylb.py +714 -0
  65. scipy/_lib/pyprima/cobyla/geometry.py +226 -0
  66. scipy/_lib/pyprima/cobyla/initialize.py +215 -0
  67. scipy/_lib/pyprima/cobyla/trustregion.py +492 -0
  68. scipy/_lib/pyprima/cobyla/update.py +289 -0
  69. scipy/_lib/pyprima/common/__init__.py +0 -0
  70. scipy/_lib/pyprima/common/_bounds.py +34 -0
  71. scipy/_lib/pyprima/common/_linear_constraints.py +46 -0
  72. scipy/_lib/pyprima/common/_nonlinear_constraints.py +54 -0
  73. scipy/_lib/pyprima/common/_project.py +173 -0
  74. scipy/_lib/pyprima/common/checkbreak.py +93 -0
  75. scipy/_lib/pyprima/common/consts.py +47 -0
  76. scipy/_lib/pyprima/common/evaluate.py +99 -0
  77. scipy/_lib/pyprima/common/history.py +38 -0
  78. scipy/_lib/pyprima/common/infos.py +30 -0
  79. scipy/_lib/pyprima/common/linalg.py +435 -0
  80. scipy/_lib/pyprima/common/message.py +290 -0
  81. scipy/_lib/pyprima/common/powalg.py +131 -0
  82. scipy/_lib/pyprima/common/preproc.py +277 -0
  83. scipy/_lib/pyprima/common/present.py +5 -0
  84. scipy/_lib/pyprima/common/ratio.py +54 -0
  85. scipy/_lib/pyprima/common/redrho.py +47 -0
  86. scipy/_lib/pyprima/common/selectx.py +296 -0
  87. scipy/_lib/tests/test__util.py +105 -121
  88. scipy/_lib/tests/test_array_api.py +166 -35
  89. scipy/_lib/tests/test_bunch.py +7 -0
  90. scipy/_lib/tests/test_ccallback.py +2 -10
  91. scipy/_lib/tests/test_public_api.py +13 -0
  92. scipy/cluster/_hierarchy.cpython-313t-darwin.so +0 -0
  93. scipy/cluster/_optimal_leaf_ordering.cpython-313t-darwin.so +0 -0
  94. scipy/cluster/_vq.cpython-313t-darwin.so +0 -0
  95. scipy/cluster/hierarchy.py +393 -223
  96. scipy/cluster/tests/test_hierarchy.py +273 -335
  97. scipy/cluster/tests/test_vq.py +45 -61
  98. scipy/cluster/vq.py +39 -35
  99. scipy/conftest.py +263 -157
  100. scipy/constants/_constants.py +4 -1
  101. scipy/constants/tests/test_codata.py +2 -2
  102. scipy/constants/tests/test_constants.py +11 -18
  103. scipy/datasets/_download_all.py +15 -1
  104. scipy/datasets/_fetchers.py +7 -1
  105. scipy/datasets/_utils.py +1 -1
  106. scipy/differentiate/_differentiate.py +25 -25
  107. scipy/differentiate/tests/test_differentiate.py +24 -25
  108. scipy/fft/_basic.py +20 -0
  109. scipy/fft/_helper.py +3 -34
  110. scipy/fft/_pocketfft/helper.py +29 -1
  111. scipy/fft/_pocketfft/tests/test_basic.py +2 -4
  112. scipy/fft/_pocketfft/tests/test_real_transforms.py +4 -4
  113. scipy/fft/_realtransforms.py +13 -0
  114. scipy/fft/tests/test_basic.py +27 -25
  115. scipy/fft/tests/test_fftlog.py +16 -7
  116. scipy/fft/tests/test_helper.py +18 -34
  117. scipy/fft/tests/test_real_transforms.py +8 -10
  118. scipy/fftpack/convolve.cpython-313t-darwin.so +0 -0
  119. scipy/fftpack/tests/test_basic.py +2 -4
  120. scipy/fftpack/tests/test_real_transforms.py +8 -9
  121. scipy/integrate/_bvp.py +9 -3
  122. scipy/integrate/_cubature.py +3 -2
  123. scipy/integrate/_dop.cpython-313t-darwin.so +0 -0
  124. scipy/integrate/_lsoda.cpython-313t-darwin.so +0 -0
  125. scipy/integrate/_ode.py +9 -2
  126. scipy/integrate/_odepack.cpython-313t-darwin.so +0 -0
  127. scipy/integrate/_quad_vec.py +21 -29
  128. scipy/integrate/_quadpack.cpython-313t-darwin.so +0 -0
  129. scipy/integrate/_quadpack_py.py +11 -7
  130. scipy/integrate/_quadrature.py +3 -3
  131. scipy/integrate/_rules/_base.py +2 -2
  132. scipy/integrate/_tanhsinh.py +48 -47
  133. scipy/integrate/_test_odeint_banded.cpython-313t-darwin.so +0 -0
  134. scipy/integrate/_vode.cpython-313t-darwin.so +0 -0
  135. scipy/integrate/tests/test__quad_vec.py +0 -6
  136. scipy/integrate/tests/test_banded_ode_solvers.py +85 -0
  137. scipy/integrate/tests/test_cubature.py +21 -35
  138. scipy/integrate/tests/test_quadrature.py +6 -8
  139. scipy/integrate/tests/test_tanhsinh.py +56 -48
  140. scipy/interpolate/__init__.py +70 -58
  141. scipy/interpolate/_bary_rational.py +22 -22
  142. scipy/interpolate/_bsplines.py +119 -66
  143. scipy/interpolate/_cubic.py +65 -50
  144. scipy/interpolate/_dfitpack.cpython-313t-darwin.so +0 -0
  145. scipy/interpolate/_dierckx.cpython-313t-darwin.so +0 -0
  146. scipy/interpolate/_fitpack.cpython-313t-darwin.so +0 -0
  147. scipy/interpolate/_fitpack2.py +9 -6
  148. scipy/interpolate/_fitpack_impl.py +32 -26
  149. scipy/interpolate/_fitpack_repro.py +23 -19
  150. scipy/interpolate/_interpnd.cpython-313t-darwin.so +0 -0
  151. scipy/interpolate/_interpolate.py +30 -12
  152. scipy/interpolate/_ndbspline.py +13 -18
  153. scipy/interpolate/_ndgriddata.py +5 -8
  154. scipy/interpolate/_polyint.py +95 -31
  155. scipy/interpolate/_ppoly.cpython-313t-darwin.so +0 -0
  156. scipy/interpolate/_rbf.py +2 -2
  157. scipy/interpolate/_rbfinterp.py +1 -1
  158. scipy/interpolate/_rbfinterp_pythran.cpython-313t-darwin.so +0 -0
  159. scipy/interpolate/_rgi.py +31 -26
  160. scipy/interpolate/_rgi_cython.cpython-313t-darwin.so +0 -0
  161. scipy/interpolate/dfitpack.py +0 -20
  162. scipy/interpolate/interpnd.py +1 -2
  163. scipy/interpolate/tests/test_bary_rational.py +2 -2
  164. scipy/interpolate/tests/test_bsplines.py +97 -1
  165. scipy/interpolate/tests/test_fitpack2.py +39 -1
  166. scipy/interpolate/tests/test_interpnd.py +32 -20
  167. scipy/interpolate/tests/test_interpolate.py +48 -4
  168. scipy/interpolate/tests/test_rgi.py +2 -1
  169. scipy/io/_fast_matrix_market/__init__.py +2 -0
  170. scipy/io/_harwell_boeing/_fortran_format_parser.py +19 -16
  171. scipy/io/_harwell_boeing/hb.py +7 -11
  172. scipy/io/_idl.py +5 -7
  173. scipy/io/_netcdf.py +15 -5
  174. scipy/io/_test_fortran.cpython-313t-darwin.so +0 -0
  175. scipy/io/arff/tests/test_arffread.py +3 -3
  176. scipy/io/matlab/__init__.py +5 -3
  177. scipy/io/matlab/_mio.py +4 -1
  178. scipy/io/matlab/_mio5.py +19 -13
  179. scipy/io/matlab/_mio5_utils.cpython-313t-darwin.so +0 -0
  180. scipy/io/matlab/_mio_utils.cpython-313t-darwin.so +0 -0
  181. scipy/io/matlab/_miobase.py +4 -1
  182. scipy/io/matlab/_streams.cpython-313t-darwin.so +0 -0
  183. scipy/io/matlab/tests/test_mio.py +46 -18
  184. scipy/io/matlab/tests/test_mio_funcs.py +1 -1
  185. scipy/io/tests/test_mmio.py +7 -1
  186. scipy/io/tests/test_wavfile.py +41 -0
  187. scipy/io/wavfile.py +57 -10
  188. scipy/linalg/_basic.py +113 -86
  189. scipy/linalg/_cythonized_array_utils.cpython-313t-darwin.so +0 -0
  190. scipy/linalg/_decomp.py +22 -9
  191. scipy/linalg/_decomp_cholesky.py +28 -13
  192. scipy/linalg/_decomp_cossin.py +45 -30
  193. scipy/linalg/_decomp_interpolative.cpython-313t-darwin.so +0 -0
  194. scipy/linalg/_decomp_ldl.py +4 -1
  195. scipy/linalg/_decomp_lu.py +18 -6
  196. scipy/linalg/_decomp_lu_cython.cpython-313t-darwin.so +0 -0
  197. scipy/linalg/_decomp_polar.py +2 -0
  198. scipy/linalg/_decomp_qr.py +6 -2
  199. scipy/linalg/_decomp_qz.py +3 -0
  200. scipy/linalg/_decomp_schur.py +3 -1
  201. scipy/linalg/_decomp_svd.py +13 -2
  202. scipy/linalg/_decomp_update.cpython-313t-darwin.so +0 -0
  203. scipy/linalg/_expm_frechet.py +4 -0
  204. scipy/linalg/_fblas.cpython-313t-darwin.so +0 -0
  205. scipy/linalg/_flapack.cpython-313t-darwin.so +0 -0
  206. scipy/linalg/_linalg_pythran.cpython-313t-darwin.so +0 -0
  207. scipy/linalg/_matfuncs.py +187 -4
  208. scipy/linalg/_matfuncs_expm.cpython-313t-darwin.so +0 -0
  209. scipy/linalg/_matfuncs_schur_sqrtm.cpython-313t-darwin.so +0 -0
  210. scipy/linalg/_matfuncs_sqrtm.py +1 -99
  211. scipy/linalg/_matfuncs_sqrtm_triu.cpython-313t-darwin.so +0 -0
  212. scipy/linalg/_procrustes.py +2 -0
  213. scipy/linalg/_sketches.py +17 -6
  214. scipy/linalg/_solve_toeplitz.cpython-313t-darwin.so +0 -0
  215. scipy/linalg/_solvers.py +7 -2
  216. scipy/linalg/_special_matrices.py +26 -36
  217. scipy/linalg/cython_blas.cpython-313t-darwin.so +0 -0
  218. scipy/linalg/cython_lapack.cpython-313t-darwin.so +0 -0
  219. scipy/linalg/lapack.py +22 -2
  220. scipy/linalg/tests/_cython_examples/meson.build +7 -0
  221. scipy/linalg/tests/test_basic.py +31 -16
  222. scipy/linalg/tests/test_batch.py +588 -0
  223. scipy/linalg/tests/test_cythonized_array_utils.py +0 -2
  224. scipy/linalg/tests/test_decomp.py +40 -3
  225. scipy/linalg/tests/test_decomp_cossin.py +14 -0
  226. scipy/linalg/tests/test_decomp_ldl.py +1 -1
  227. scipy/linalg/tests/test_lapack.py +115 -7
  228. scipy/linalg/tests/test_matfuncs.py +157 -102
  229. scipy/linalg/tests/test_procrustes.py +0 -7
  230. scipy/linalg/tests/test_solve_toeplitz.py +1 -1
  231. scipy/linalg/tests/test_special_matrices.py +1 -5
  232. scipy/ndimage/__init__.py +1 -0
  233. scipy/ndimage/_cytest.cpython-313t-darwin.so +0 -0
  234. scipy/ndimage/_delegators.py +8 -2
  235. scipy/ndimage/_filters.py +453 -5
  236. scipy/ndimage/_interpolation.py +36 -6
  237. scipy/ndimage/_measurements.py +4 -2
  238. scipy/ndimage/_morphology.py +5 -0
  239. scipy/ndimage/_nd_image.cpython-313t-darwin.so +0 -0
  240. scipy/ndimage/_ni_docstrings.py +5 -1
  241. scipy/ndimage/_ni_label.cpython-313t-darwin.so +0 -0
  242. scipy/ndimage/_ni_support.py +1 -5
  243. scipy/ndimage/_rank_filter_1d.cpython-313t-darwin.so +0 -0
  244. scipy/ndimage/_support_alternative_backends.py +18 -6
  245. scipy/ndimage/tests/test_filters.py +370 -259
  246. scipy/ndimage/tests/test_fourier.py +7 -9
  247. scipy/ndimage/tests/test_interpolation.py +68 -61
  248. scipy/ndimage/tests/test_measurements.py +18 -35
  249. scipy/ndimage/tests/test_morphology.py +143 -131
  250. scipy/ndimage/tests/test_splines.py +1 -3
  251. scipy/odr/__odrpack.cpython-313t-darwin.so +0 -0
  252. scipy/optimize/_basinhopping.py +13 -7
  253. scipy/optimize/_bglu_dense.cpython-313t-darwin.so +0 -0
  254. scipy/optimize/_bracket.py +17 -24
  255. scipy/optimize/_chandrupatla.py +9 -10
  256. scipy/optimize/_cobyla_py.py +104 -123
  257. scipy/optimize/_constraints.py +14 -10
  258. scipy/optimize/_differentiable_functions.py +371 -230
  259. scipy/optimize/_differentialevolution.py +4 -3
  260. scipy/optimize/_direct.cpython-313t-darwin.so +0 -0
  261. scipy/optimize/_dual_annealing.py +1 -1
  262. scipy/optimize/_elementwise.py +1 -4
  263. scipy/optimize/_group_columns.cpython-313t-darwin.so +0 -0
  264. scipy/optimize/_lbfgsb.cpython-313t-darwin.so +0 -0
  265. scipy/optimize/_lbfgsb_py.py +57 -16
  266. scipy/optimize/_linprog_doc.py +2 -2
  267. scipy/optimize/_linprog_highs.py +2 -2
  268. scipy/optimize/_linprog_ip.py +25 -10
  269. scipy/optimize/_linprog_util.py +14 -16
  270. scipy/optimize/_lsap.cpython-313t-darwin.so +0 -0
  271. scipy/optimize/_lsq/common.py +3 -3
  272. scipy/optimize/_lsq/dogbox.py +16 -2
  273. scipy/optimize/_lsq/givens_elimination.cpython-313t-darwin.so +0 -0
  274. scipy/optimize/_lsq/least_squares.py +198 -126
  275. scipy/optimize/_lsq/lsq_linear.py +6 -6
  276. scipy/optimize/_lsq/trf.py +35 -8
  277. scipy/optimize/_milp.py +3 -1
  278. scipy/optimize/_minimize.py +105 -36
  279. scipy/optimize/_minpack.cpython-313t-darwin.so +0 -0
  280. scipy/optimize/_minpack_py.py +21 -14
  281. scipy/optimize/_moduleTNC.cpython-313t-darwin.so +0 -0
  282. scipy/optimize/_nnls.py +20 -21
  283. scipy/optimize/_nonlin.py +34 -3
  284. scipy/optimize/_numdiff.py +288 -110
  285. scipy/optimize/_optimize.py +86 -48
  286. scipy/optimize/_pava_pybind.cpython-313t-darwin.so +0 -0
  287. scipy/optimize/_remove_redundancy.py +5 -5
  288. scipy/optimize/_root_scalar.py +1 -1
  289. scipy/optimize/_shgo.py +6 -0
  290. scipy/optimize/_shgo_lib/_complex.py +1 -1
  291. scipy/optimize/_slsqp_py.py +216 -124
  292. scipy/optimize/_slsqplib.cpython-313t-darwin.so +0 -0
  293. scipy/optimize/_spectral.py +1 -1
  294. scipy/optimize/_tnc.py +8 -1
  295. scipy/optimize/_trlib/_trlib.cpython-313t-darwin.so +0 -0
  296. scipy/optimize/_trustregion.py +20 -6
  297. scipy/optimize/_trustregion_constr/canonical_constraint.py +7 -7
  298. scipy/optimize/_trustregion_constr/equality_constrained_sqp.py +1 -1
  299. scipy/optimize/_trustregion_constr/minimize_trustregion_constr.py +11 -3
  300. scipy/optimize/_trustregion_constr/projections.py +12 -8
  301. scipy/optimize/_trustregion_constr/qp_subproblem.py +9 -9
  302. scipy/optimize/_trustregion_constr/tests/test_projections.py +7 -7
  303. scipy/optimize/_trustregion_constr/tests/test_qp_subproblem.py +77 -77
  304. scipy/optimize/_trustregion_constr/tr_interior_point.py +5 -5
  305. scipy/optimize/_trustregion_exact.py +0 -1
  306. scipy/optimize/_zeros.cpython-313t-darwin.so +0 -0
  307. scipy/optimize/_zeros_py.py +97 -17
  308. scipy/optimize/cython_optimize/_zeros.cpython-313t-darwin.so +0 -0
  309. scipy/optimize/slsqp.py +0 -1
  310. scipy/optimize/tests/test__basinhopping.py +1 -1
  311. scipy/optimize/tests/test__differential_evolution.py +4 -4
  312. scipy/optimize/tests/test__linprog_clean_inputs.py +5 -3
  313. scipy/optimize/tests/test__numdiff.py +66 -22
  314. scipy/optimize/tests/test__remove_redundancy.py +2 -2
  315. scipy/optimize/tests/test__shgo.py +9 -1
  316. scipy/optimize/tests/test_bracket.py +36 -46
  317. scipy/optimize/tests/test_chandrupatla.py +133 -135
  318. scipy/optimize/tests/test_cobyla.py +74 -45
  319. scipy/optimize/tests/test_constraints.py +1 -1
  320. scipy/optimize/tests/test_differentiable_functions.py +226 -6
  321. scipy/optimize/tests/test_lbfgsb_hessinv.py +22 -0
  322. scipy/optimize/tests/test_least_squares.py +125 -13
  323. scipy/optimize/tests/test_linear_assignment.py +3 -3
  324. scipy/optimize/tests/test_linprog.py +3 -3
  325. scipy/optimize/tests/test_lsq_linear.py +6 -6
  326. scipy/optimize/tests/test_minimize_constrained.py +2 -2
  327. scipy/optimize/tests/test_minpack.py +4 -4
  328. scipy/optimize/tests/test_nnls.py +43 -3
  329. scipy/optimize/tests/test_nonlin.py +36 -0
  330. scipy/optimize/tests/test_optimize.py +95 -17
  331. scipy/optimize/tests/test_slsqp.py +36 -4
  332. scipy/optimize/tests/test_zeros.py +34 -1
  333. scipy/signal/__init__.py +12 -23
  334. scipy/signal/_delegators.py +568 -0
  335. scipy/signal/_filter_design.py +459 -241
  336. scipy/signal/_fir_filter_design.py +262 -90
  337. scipy/signal/_lti_conversion.py +3 -2
  338. scipy/signal/_ltisys.py +118 -91
  339. scipy/signal/_max_len_seq_inner.cpython-313t-darwin.so +0 -0
  340. scipy/signal/_peak_finding_utils.cpython-313t-darwin.so +0 -0
  341. scipy/signal/_polyutils.py +172 -0
  342. scipy/signal/_short_time_fft.py +519 -70
  343. scipy/signal/_signal_api.py +30 -0
  344. scipy/signal/_signaltools.py +719 -399
  345. scipy/signal/_sigtools.cpython-313t-darwin.so +0 -0
  346. scipy/signal/_sosfilt.cpython-313t-darwin.so +0 -0
  347. scipy/signal/_spectral_py.py +230 -50
  348. scipy/signal/_spline.cpython-313t-darwin.so +0 -0
  349. scipy/signal/_spline_filters.py +108 -68
  350. scipy/signal/_support_alternative_backends.py +73 -0
  351. scipy/signal/_upfirdn.py +4 -1
  352. scipy/signal/_upfirdn_apply.cpython-313t-darwin.so +0 -0
  353. scipy/signal/_waveforms.py +2 -11
  354. scipy/signal/_wavelets.py +1 -1
  355. scipy/signal/fir_filter_design.py +1 -0
  356. scipy/signal/spline.py +4 -11
  357. scipy/signal/tests/_scipy_spectral_test_shim.py +2 -171
  358. scipy/signal/tests/test_bsplines.py +114 -79
  359. scipy/signal/tests/test_cont2discrete.py +9 -2
  360. scipy/signal/tests/test_filter_design.py +721 -481
  361. scipy/signal/tests/test_fir_filter_design.py +332 -140
  362. scipy/signal/tests/test_savitzky_golay.py +4 -3
  363. scipy/signal/tests/test_short_time_fft.py +221 -3
  364. scipy/signal/tests/test_signaltools.py +2144 -1348
  365. scipy/signal/tests/test_spectral.py +50 -6
  366. scipy/signal/tests/test_splines.py +161 -96
  367. scipy/signal/tests/test_upfirdn.py +84 -50
  368. scipy/signal/tests/test_waveforms.py +20 -0
  369. scipy/signal/tests/test_windows.py +607 -466
  370. scipy/signal/windows/_windows.py +287 -148
  371. scipy/sparse/__init__.py +23 -4
  372. scipy/sparse/_base.py +270 -108
  373. scipy/sparse/_bsr.py +7 -4
  374. scipy/sparse/_compressed.py +59 -231
  375. scipy/sparse/_construct.py +90 -38
  376. scipy/sparse/_coo.py +115 -181
  377. scipy/sparse/_csc.py +4 -4
  378. scipy/sparse/_csparsetools.cpython-313t-darwin.so +0 -0
  379. scipy/sparse/_csr.py +2 -2
  380. scipy/sparse/_data.py +48 -48
  381. scipy/sparse/_dia.py +105 -18
  382. scipy/sparse/_dok.py +0 -23
  383. scipy/sparse/_index.py +4 -4
  384. scipy/sparse/_matrix.py +23 -0
  385. scipy/sparse/_sparsetools.cpython-313t-darwin.so +0 -0
  386. scipy/sparse/_sputils.py +37 -22
  387. scipy/sparse/base.py +0 -9
  388. scipy/sparse/bsr.py +0 -14
  389. scipy/sparse/compressed.py +0 -23
  390. scipy/sparse/construct.py +0 -6
  391. scipy/sparse/coo.py +0 -14
  392. scipy/sparse/csc.py +0 -3
  393. scipy/sparse/csgraph/_flow.cpython-313t-darwin.so +0 -0
  394. scipy/sparse/csgraph/_matching.cpython-313t-darwin.so +0 -0
  395. scipy/sparse/csgraph/_min_spanning_tree.cpython-313t-darwin.so +0 -0
  396. scipy/sparse/csgraph/_reordering.cpython-313t-darwin.so +0 -0
  397. scipy/sparse/csgraph/_shortest_path.cpython-313t-darwin.so +0 -0
  398. scipy/sparse/csgraph/_tools.cpython-313t-darwin.so +0 -0
  399. scipy/sparse/csgraph/_traversal.cpython-313t-darwin.so +0 -0
  400. scipy/sparse/csgraph/tests/test_matching.py +14 -2
  401. scipy/sparse/csgraph/tests/test_pydata_sparse.py +4 -1
  402. scipy/sparse/csgraph/tests/test_shortest_path.py +83 -27
  403. scipy/sparse/csr.py +0 -5
  404. scipy/sparse/data.py +1 -6
  405. scipy/sparse/dia.py +0 -7
  406. scipy/sparse/dok.py +0 -10
  407. scipy/sparse/linalg/_dsolve/_superlu.cpython-313t-darwin.so +0 -0
  408. scipy/sparse/linalg/_dsolve/linsolve.py +9 -0
  409. scipy/sparse/linalg/_dsolve/tests/test_linsolve.py +35 -28
  410. scipy/sparse/linalg/_eigen/arpack/_arpack.cpython-313t-darwin.so +0 -0
  411. scipy/sparse/linalg/_eigen/arpack/arpack.py +23 -17
  412. scipy/sparse/linalg/_eigen/lobpcg/lobpcg.py +6 -6
  413. scipy/sparse/linalg/_interface.py +17 -18
  414. scipy/sparse/linalg/_isolve/_gcrotmk.py +4 -4
  415. scipy/sparse/linalg/_isolve/iterative.py +51 -45
  416. scipy/sparse/linalg/_isolve/lgmres.py +6 -6
  417. scipy/sparse/linalg/_isolve/minres.py +5 -5
  418. scipy/sparse/linalg/_isolve/tfqmr.py +7 -7
  419. scipy/sparse/linalg/_isolve/utils.py +2 -8
  420. scipy/sparse/linalg/_matfuncs.py +1 -1
  421. scipy/sparse/linalg/_norm.py +1 -1
  422. scipy/sparse/linalg/_propack/_cpropack.cpython-313t-darwin.so +0 -0
  423. scipy/sparse/linalg/_propack/_dpropack.cpython-313t-darwin.so +0 -0
  424. scipy/sparse/linalg/_propack/_spropack.cpython-313t-darwin.so +0 -0
  425. scipy/sparse/linalg/_propack/_zpropack.cpython-313t-darwin.so +0 -0
  426. scipy/sparse/linalg/_special_sparse_arrays.py +39 -38
  427. scipy/sparse/linalg/tests/test_pydata_sparse.py +14 -0
  428. scipy/sparse/tests/test_arithmetic1d.py +5 -2
  429. scipy/sparse/tests/test_base.py +214 -42
  430. scipy/sparse/tests/test_common1d.py +7 -7
  431. scipy/sparse/tests/test_construct.py +1 -1
  432. scipy/sparse/tests/test_coo.py +272 -4
  433. scipy/sparse/tests/test_sparsetools.py +5 -0
  434. scipy/sparse/tests/test_sputils.py +36 -7
  435. scipy/spatial/_ckdtree.cpython-313t-darwin.so +0 -0
  436. scipy/spatial/_distance_pybind.cpython-313t-darwin.so +0 -0
  437. scipy/spatial/_distance_wrap.cpython-313t-darwin.so +0 -0
  438. scipy/spatial/_hausdorff.cpython-313t-darwin.so +0 -0
  439. scipy/spatial/_qhull.cpython-313t-darwin.so +0 -0
  440. scipy/spatial/_voronoi.cpython-313t-darwin.so +0 -0
  441. scipy/spatial/distance.py +49 -42
  442. scipy/spatial/tests/test_distance.py +15 -1
  443. scipy/spatial/tests/test_kdtree.py +1 -0
  444. scipy/spatial/tests/test_qhull.py +7 -2
  445. scipy/spatial/transform/__init__.py +5 -3
  446. scipy/spatial/transform/_rigid_transform.cpython-313t-darwin.so +0 -0
  447. scipy/spatial/transform/_rotation.cpython-313t-darwin.so +0 -0
  448. scipy/spatial/transform/tests/test_rigid_transform.py +1221 -0
  449. scipy/spatial/transform/tests/test_rotation.py +1213 -832
  450. scipy/spatial/transform/tests/test_rotation_groups.py +3 -3
  451. scipy/spatial/transform/tests/test_rotation_spline.py +29 -8
  452. scipy/special/__init__.py +1 -47
  453. scipy/special/_add_newdocs.py +34 -772
  454. scipy/special/_basic.py +22 -25
  455. scipy/special/_comb.cpython-313t-darwin.so +0 -0
  456. scipy/special/_ellip_harm_2.cpython-313t-darwin.so +0 -0
  457. scipy/special/_gufuncs.cpython-313t-darwin.so +0 -0
  458. scipy/special/_logsumexp.py +67 -58
  459. scipy/special/_orthogonal.pyi +1 -1
  460. scipy/special/_specfun.cpython-313t-darwin.so +0 -0
  461. scipy/special/_special_ufuncs.cpython-313t-darwin.so +0 -0
  462. scipy/special/_spherical_bessel.py +4 -4
  463. scipy/special/_support_alternative_backends.py +212 -119
  464. scipy/special/_test_internal.cpython-313t-darwin.so +0 -0
  465. scipy/special/_testutils.py +4 -4
  466. scipy/special/_ufuncs.cpython-313t-darwin.so +0 -0
  467. scipy/special/_ufuncs.pyi +1 -0
  468. scipy/special/_ufuncs.pyx +215 -1400
  469. scipy/special/_ufuncs_cxx.cpython-313t-darwin.so +0 -0
  470. scipy/special/_ufuncs_cxx.pxd +2 -15
  471. scipy/special/_ufuncs_cxx.pyx +5 -44
  472. scipy/special/_ufuncs_cxx_defs.h +2 -16
  473. scipy/special/_ufuncs_defs.h +0 -8
  474. scipy/special/cython_special.cpython-313t-darwin.so +0 -0
  475. scipy/special/cython_special.pxd +1 -1
  476. scipy/special/tests/_cython_examples/meson.build +10 -1
  477. scipy/special/tests/test_basic.py +153 -20
  478. scipy/special/tests/test_boost_ufuncs.py +3 -0
  479. scipy/special/tests/test_cdflib.py +35 -11
  480. scipy/special/tests/test_gammainc.py +16 -0
  481. scipy/special/tests/test_hyp2f1.py +2 -2
  482. scipy/special/tests/test_log1mexp.py +85 -0
  483. scipy/special/tests/test_logsumexp.py +206 -64
  484. scipy/special/tests/test_mpmath.py +1 -0
  485. scipy/special/tests/test_nan_inputs.py +1 -1
  486. scipy/special/tests/test_orthogonal.py +17 -18
  487. scipy/special/tests/test_sf_error.py +3 -2
  488. scipy/special/tests/test_sph_harm.py +6 -7
  489. scipy/special/tests/test_support_alternative_backends.py +211 -76
  490. scipy/stats/__init__.py +4 -1
  491. scipy/stats/_ansari_swilk_statistics.cpython-313t-darwin.so +0 -0
  492. scipy/stats/_axis_nan_policy.py +5 -12
  493. scipy/stats/_biasedurn.cpython-313t-darwin.so +0 -0
  494. scipy/stats/_continued_fraction.py +387 -0
  495. scipy/stats/_continuous_distns.py +277 -310
  496. scipy/stats/_correlation.py +1 -1
  497. scipy/stats/_covariance.py +6 -3
  498. scipy/stats/_discrete_distns.py +39 -32
  499. scipy/stats/_distn_infrastructure.py +39 -12
  500. scipy/stats/_distribution_infrastructure.py +900 -238
  501. scipy/stats/_entropy.py +9 -10
  502. scipy/{_lib → stats}/_finite_differences.py +1 -1
  503. scipy/stats/_hypotests.py +83 -50
  504. scipy/stats/_kde.py +53 -49
  505. scipy/stats/_ksstats.py +1 -1
  506. scipy/stats/_levy_stable/__init__.py +7 -15
  507. scipy/stats/_levy_stable/levyst.cpython-313t-darwin.so +0 -0
  508. scipy/stats/_morestats.py +118 -73
  509. scipy/stats/_mstats_basic.py +13 -17
  510. scipy/stats/_mstats_extras.py +8 -8
  511. scipy/stats/_multivariate.py +89 -113
  512. scipy/stats/_new_distributions.py +97 -20
  513. scipy/stats/_page_trend_test.py +12 -5
  514. scipy/stats/_probability_distribution.py +265 -43
  515. scipy/stats/_qmc.py +14 -9
  516. scipy/stats/_qmc_cy.cpython-313t-darwin.so +0 -0
  517. scipy/stats/_qmvnt.py +16 -95
  518. scipy/stats/_qmvnt_cy.cpython-313t-darwin.so +0 -0
  519. scipy/stats/_quantile.py +335 -0
  520. scipy/stats/_rcont/rcont.cpython-313t-darwin.so +0 -0
  521. scipy/stats/_resampling.py +4 -29
  522. scipy/stats/_sampling.py +1 -1
  523. scipy/stats/_sobol.cpython-313t-darwin.so +0 -0
  524. scipy/stats/_stats.cpython-313t-darwin.so +0 -0
  525. scipy/stats/_stats_mstats_common.py +21 -2
  526. scipy/stats/_stats_py.py +550 -476
  527. scipy/stats/_stats_pythran.cpython-313t-darwin.so +0 -0
  528. scipy/stats/_unuran/unuran_wrapper.cpython-313t-darwin.so +0 -0
  529. scipy/stats/_unuran/unuran_wrapper.pyi +2 -1
  530. scipy/stats/_variation.py +6 -8
  531. scipy/stats/_wilcoxon.py +13 -7
  532. scipy/stats/tests/common_tests.py +6 -4
  533. scipy/stats/tests/test_axis_nan_policy.py +62 -24
  534. scipy/stats/tests/test_continued_fraction.py +173 -0
  535. scipy/stats/tests/test_continuous.py +379 -60
  536. scipy/stats/tests/test_continuous_basic.py +18 -12
  537. scipy/stats/tests/test_discrete_basic.py +14 -8
  538. scipy/stats/tests/test_discrete_distns.py +16 -16
  539. scipy/stats/tests/test_distributions.py +95 -75
  540. scipy/stats/tests/test_entropy.py +40 -48
  541. scipy/stats/tests/test_fit.py +4 -3
  542. scipy/stats/tests/test_hypotests.py +153 -24
  543. scipy/stats/tests/test_kdeoth.py +109 -41
  544. scipy/stats/tests/test_marray.py +289 -0
  545. scipy/stats/tests/test_morestats.py +79 -47
  546. scipy/stats/tests/test_mstats_basic.py +3 -3
  547. scipy/stats/tests/test_multivariate.py +434 -83
  548. scipy/stats/tests/test_qmc.py +13 -10
  549. scipy/stats/tests/test_quantile.py +199 -0
  550. scipy/stats/tests/test_rank.py +119 -112
  551. scipy/stats/tests/test_resampling.py +47 -56
  552. scipy/stats/tests/test_sampling.py +9 -4
  553. scipy/stats/tests/test_stats.py +799 -939
  554. scipy/stats/tests/test_variation.py +8 -6
  555. scipy/version.py +2 -2
  556. {scipy-1.15.3.dist-info → scipy-1.16.0rc2.dist-info}/LICENSE.txt +4 -4
  557. {scipy-1.15.3.dist-info → scipy-1.16.0rc2.dist-info}/METADATA +11 -11
  558. {scipy-1.15.3.dist-info → scipy-1.16.0rc2.dist-info}/RECORD +559 -566
  559. scipy-1.16.0rc2.dist-info/WHEEL +6 -0
  560. scipy/_lib/array_api_extra/_funcs.py +0 -484
  561. scipy/_lib/array_api_extra/_typing.py +0 -8
  562. scipy/interpolate/_bspl.cpython-313t-darwin.so +0 -0
  563. scipy/optimize/_cobyla.cpython-313t-darwin.so +0 -0
  564. scipy/optimize/_cython_nnls.cpython-313t-darwin.so +0 -0
  565. scipy/optimize/_slsqp.cpython-313t-darwin.so +0 -0
  566. scipy/spatial/qhull_src/COPYING.txt +0 -38
  567. scipy/special/libsf_error_state.dylib +0 -0
  568. scipy/special/tests/test_log_softmax.py +0 -109
  569. scipy/special/tests/test_xsf_cuda.py +0 -114
  570. scipy/special/xsf/binom.h +0 -89
  571. scipy/special/xsf/cdflib.h +0 -100
  572. scipy/special/xsf/cephes/airy.h +0 -307
  573. scipy/special/xsf/cephes/besselpoly.h +0 -51
  574. scipy/special/xsf/cephes/beta.h +0 -257
  575. scipy/special/xsf/cephes/cbrt.h +0 -131
  576. scipy/special/xsf/cephes/chbevl.h +0 -85
  577. scipy/special/xsf/cephes/chdtr.h +0 -193
  578. scipy/special/xsf/cephes/const.h +0 -87
  579. scipy/special/xsf/cephes/ellie.h +0 -293
  580. scipy/special/xsf/cephes/ellik.h +0 -251
  581. scipy/special/xsf/cephes/ellpe.h +0 -107
  582. scipy/special/xsf/cephes/ellpk.h +0 -117
  583. scipy/special/xsf/cephes/expn.h +0 -260
  584. scipy/special/xsf/cephes/gamma.h +0 -398
  585. scipy/special/xsf/cephes/hyp2f1.h +0 -596
  586. scipy/special/xsf/cephes/hyperg.h +0 -361
  587. scipy/special/xsf/cephes/i0.h +0 -149
  588. scipy/special/xsf/cephes/i1.h +0 -158
  589. scipy/special/xsf/cephes/igam.h +0 -421
  590. scipy/special/xsf/cephes/igam_asymp_coeff.h +0 -195
  591. scipy/special/xsf/cephes/igami.h +0 -313
  592. scipy/special/xsf/cephes/j0.h +0 -225
  593. scipy/special/xsf/cephes/j1.h +0 -198
  594. scipy/special/xsf/cephes/jv.h +0 -715
  595. scipy/special/xsf/cephes/k0.h +0 -164
  596. scipy/special/xsf/cephes/k1.h +0 -163
  597. scipy/special/xsf/cephes/kn.h +0 -243
  598. scipy/special/xsf/cephes/lanczos.h +0 -112
  599. scipy/special/xsf/cephes/ndtr.h +0 -275
  600. scipy/special/xsf/cephes/poch.h +0 -85
  601. scipy/special/xsf/cephes/polevl.h +0 -167
  602. scipy/special/xsf/cephes/psi.h +0 -194
  603. scipy/special/xsf/cephes/rgamma.h +0 -111
  604. scipy/special/xsf/cephes/scipy_iv.h +0 -811
  605. scipy/special/xsf/cephes/shichi.h +0 -248
  606. scipy/special/xsf/cephes/sici.h +0 -224
  607. scipy/special/xsf/cephes/sindg.h +0 -221
  608. scipy/special/xsf/cephes/tandg.h +0 -139
  609. scipy/special/xsf/cephes/trig.h +0 -58
  610. scipy/special/xsf/cephes/unity.h +0 -186
  611. scipy/special/xsf/cephes/zeta.h +0 -172
  612. scipy/special/xsf/config.h +0 -304
  613. scipy/special/xsf/digamma.h +0 -205
  614. scipy/special/xsf/error.h +0 -57
  615. scipy/special/xsf/evalpoly.h +0 -47
  616. scipy/special/xsf/expint.h +0 -266
  617. scipy/special/xsf/hyp2f1.h +0 -694
  618. scipy/special/xsf/iv_ratio.h +0 -173
  619. scipy/special/xsf/lambertw.h +0 -150
  620. scipy/special/xsf/loggamma.h +0 -163
  621. scipy/special/xsf/sici.h +0 -200
  622. scipy/special/xsf/tools.h +0 -427
  623. scipy/special/xsf/trig.h +0 -164
  624. scipy/special/xsf/wright_bessel.h +0 -843
  625. scipy/special/xsf/zlog1.h +0 -35
  626. scipy/stats/_mvn.cpython-313t-darwin.so +0 -0
  627. scipy-1.15.3.dist-info/WHEEL +0 -4
@@ -4,9 +4,10 @@ import numpy as np
4
4
  from numpy.linalg import norm
5
5
 
6
6
  from scipy.sparse.linalg import LinearOperator
7
- from ..sparse import issparse, csc_matrix, csr_matrix, coo_matrix, find
7
+ from ..sparse import issparse, isspmatrix, find, csc_array, csr_array, csr_matrix
8
8
  from ._group_columns import group_dense, group_sparse
9
9
  from scipy._lib._array_api import array_namespace
10
+ from scipy._lib._util import MapWrapper
10
11
  from scipy._lib import array_api_extra as xpx
11
12
 
12
13
 
@@ -221,7 +222,7 @@ def group_columns(A, order=0):
221
222
 
222
223
  Parameters
223
224
  ----------
224
- A : array_like or sparse matrix, shape (m, n)
225
+ A : array_like or sparse array, shape (m, n)
225
226
  Matrix of which to group columns.
226
227
  order : int, iterable of int with shape (n,) or None
227
228
  Permutation array which defines the order of columns enumeration.
@@ -244,7 +245,7 @@ def group_columns(A, order=0):
244
245
  and its Applications, 13 (1974), pp. 117-120.
245
246
  """
246
247
  if issparse(A):
247
- A = csc_matrix(A)
248
+ A = csc_array(A)
248
249
  else:
249
250
  A = np.atleast_2d(A)
250
251
  A = (A != 0).astype(np.int32)
@@ -276,7 +277,8 @@ def group_columns(A, order=0):
276
277
 
277
278
  def approx_derivative(fun, x0, method='3-point', rel_step=None, abs_step=None,
278
279
  f0=None, bounds=(-np.inf, np.inf), sparsity=None,
279
- as_linear_operator=False, args=(), kwargs=None):
280
+ as_linear_operator=False, args=(), kwargs=None,
281
+ full_output=False, workers=None):
280
282
  """Compute finite difference approximation of the derivatives of a
281
283
  vector-valued function.
282
284
 
@@ -325,20 +327,20 @@ def approx_derivative(fun, x0, method='3-point', rel_step=None, abs_step=None,
325
327
  case the bound will be the same for all variables. Use it to limit the
326
328
  range of function evaluation. Bounds checking is not implemented
327
329
  when `as_linear_operator` is True.
328
- sparsity : {None, array_like, sparse matrix, 2-tuple}, optional
330
+ sparsity : {None, array_like, sparse array, 2-tuple}, optional
329
331
  Defines a sparsity structure of the Jacobian matrix. If the Jacobian
330
332
  matrix is known to have only few non-zero elements in each row, then
331
333
  it's possible to estimate its several columns by a single function
332
334
  evaluation [3]_. To perform such economic computations two ingredients
333
335
  are required:
334
336
 
335
- * structure : array_like or sparse matrix of shape (m, n). A zero
337
+ * structure : array_like or sparse array of shape (m, n). A zero
336
338
  element means that a corresponding element of the Jacobian
337
339
  identically equals to zero.
338
340
  * groups : array_like of shape (n,). A column grouping for a given
339
341
  sparsity structure, use `group_columns` to obtain it.
340
342
 
341
- A single array or a sparse matrix is interpreted as a sparsity
343
+ A single array or a sparse array is interpreted as a sparsity
342
344
  structure, and groups are computed inside the function. A tuple is
343
345
  interpreted as (structure, groups). If None (default), a standard
344
346
  dense differencing will be used.
@@ -347,7 +349,7 @@ def approx_derivative(fun, x0, method='3-point', rel_step=None, abs_step=None,
347
349
  matrices where each row contains few non-zero elements.
348
350
  as_linear_operator : bool, optional
349
351
  When True the function returns an `scipy.sparse.linalg.LinearOperator`.
350
- Otherwise it returns a dense array or a sparse matrix depending on
352
+ Otherwise it returns a dense array or a sparse array depending on
351
353
  `sparsity`. The linear operator provides an efficient way of computing
352
354
  ``J.dot(p)`` for any vector ``p`` of shape (n,), but does not allow
353
355
  direct access to individual elements of the matrix. By default
@@ -355,20 +357,44 @@ def approx_derivative(fun, x0, method='3-point', rel_step=None, abs_step=None,
355
357
  args, kwargs : tuple and dict, optional
356
358
  Additional arguments passed to `fun`. Both empty by default.
357
359
  The calling signature is ``fun(x, *args, **kwargs)``.
360
+ full_output : bool, optional
361
+ If True then the function also returns a dictionary with extra information
362
+ about the calculation.
363
+ workers : int or map-like callable, optional
364
+ Supply a map-like callable, such as
365
+ `multiprocessing.Pool.map` for evaluating the population in parallel.
366
+ This evaluation is carried out as ``workers(fun, iterable)``.
367
+ Alternatively, if `workers` is an int the task is subdivided into `workers`
368
+ sections and the fun evaluated in parallel
369
+ (uses `multiprocessing.Pool <multiprocessing>`).
370
+ Supply -1 to use all available CPU cores.
371
+ It is recommended that a map-like be used instead of int, as repeated
372
+ calls to `approx_derivative` will incur large overhead from setting up
373
+ new processes.
358
374
 
359
375
  Returns
360
376
  -------
361
- J : {ndarray, sparse matrix, LinearOperator}
377
+ J : {ndarray, sparse array, LinearOperator}
362
378
  Finite difference approximation of the Jacobian matrix.
363
379
  If `as_linear_operator` is True returns a LinearOperator
364
380
  with shape (m, n). Otherwise it returns a dense array or sparse
365
- matrix depending on how `sparsity` is defined. If `sparsity`
381
+ array depending on how `sparsity` is defined. If `sparsity`
366
382
  is None then a ndarray with shape (m, n) is returned. If
367
- `sparsity` is not None returns a csr_matrix with shape (m, n).
368
- For sparse matrices and linear operators it is always returned as
369
- a 2-D structure, for ndarrays, if m=1 it is returned
383
+ `sparsity` is not None returns a csr_array or csr_matrix with
384
+ shape (m, n) following the array/matrix type of the incoming structure.
385
+ For sparse arrays and linear operators it is always returned as
386
+ a 2-D structure. For ndarrays, if m=1 it is returned
370
387
  as a 1-D gradient array with shape (n,).
371
388
 
389
+ info_dict : dict
390
+ Dictionary containing extra information about the calculation. The
391
+ keys include:
392
+
393
+ - `nfev`, number of function evaluations. If `as_linear_operator` is True
394
+ then `fun` is expected to track the number of evaluations itself.
395
+ This is because multiple calls may be made to the linear operator which
396
+ are not trackable here.
397
+
372
398
  See Also
373
399
  --------
374
400
  check_derivative : Check correctness of a function computing derivatives.
@@ -436,10 +462,51 @@ def approx_derivative(fun, x0, method='3-point', rel_step=None, abs_step=None,
436
462
  array([ 1.])
437
463
  >>> approx_derivative(g, x0, bounds=(1.0, np.inf))
438
464
  array([ 2.])
465
+
466
+ We can also parallelize the derivative calculation using the workers
467
+ keyword.
468
+
469
+ >>> from multiprocessing import Pool
470
+ >>> import time
471
+ >>> def fun2(x): # import from an external file for use with multiprocessing
472
+ ... time.sleep(0.002)
473
+ ... return rosen(x)
474
+
475
+ >>> rng = np.random.default_rng()
476
+ >>> x0 = rng.uniform(high=10, size=(2000,))
477
+ >>> f0 = rosen(x0)
478
+
479
+ >>> %timeit approx_derivative(fun2, x0, f0=f0) # may vary
480
+ 10.5 s ± 5.91 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
481
+
482
+ >>> elapsed = []
483
+ >>> with Pool() as workers:
484
+ ... for i in range(10):
485
+ ... t = time.perf_counter()
486
+ ... approx_derivative(fun2, x0, workers=workers.map, f0=f0)
487
+ ... et = time.perf_counter()
488
+ ... elapsed.append(et - t)
489
+ >>> np.mean(elapsed) # may vary
490
+ np.float64(1.442545195999901)
491
+
492
+ Create a map-like vectorized version. `x` is a generator, so first of all
493
+ a 2-D array, `xx`, is reconstituted. Here `xx` has shape `(Y, N)` where `Y`
494
+ is the number of function evaluations to perform and `N` is the dimensionality
495
+ of the objective function. The underlying objective function is `rosen`, which
496
+ requires `xx` to have shape `(N, Y)`, so a transpose is required.
497
+
498
+ >>> def fun(f, x, *args, **kwds):
499
+ ... xx = np.r_[[xs for xs in x]]
500
+ ... return f(xx.T)
501
+ >>> %timeit approx_derivative(fun2, x0, workers=fun, f0=f0) # may vary
502
+ 91.8 ms ± 755 μs per loop (mean ± std. dev. of 7 runs, 10 loops each)
503
+
439
504
  """
440
505
  if method not in ['2-point', '3-point', 'cs']:
441
506
  raise ValueError(f"Unknown method '{method}'. ")
442
507
 
508
+ info_dict = {'nfev': None}
509
+
443
510
  xp = array_namespace(x0)
444
511
  _x = xpx.atleast_nd(xp.asarray(x0), ndim=1, xp=xp)
445
512
  _dtype = xp.float64
@@ -465,20 +532,20 @@ def approx_derivative(fun, x0, method='3-point', rel_step=None, abs_step=None,
465
532
  if kwargs is None:
466
533
  kwargs = {}
467
534
 
468
- def fun_wrapped(x):
469
- # send user function same fp type as x0. (but only if cs is not being
470
- # used
471
- if xp.isdtype(x.dtype, "real floating"):
472
- x = xp.astype(x, x0.dtype)
535
+ fun_wrapped = _Fun_Wrapper(fun, x0, args, kwargs)
473
536
 
474
- f = np.atleast_1d(fun(x, *args, **kwargs))
475
- if f.ndim > 1:
476
- raise RuntimeError("`fun` return value has "
477
- "more than 1 dimension.")
478
- return f
537
+ # Record how function evaluations are consumed by `approx_derivative`.
538
+ # Historically this was done by upstream functions wrapping `fun`.
539
+ # However, with parallelization via workers it was going to be impossible to
540
+ # keep that counter updated across Processes. Counter synchronisation can
541
+ # be achieved via multiprocessing.Value and a Pool. However, workers can be
542
+ # any map-like, not necessarily a Pool, so initialization of the Value would
543
+ # be difficult.
544
+ nfev = _nfev = 0
479
545
 
480
546
  if f0 is None:
481
547
  f0 = fun_wrapped(x0)
548
+ nfev = 1
482
549
  else:
483
550
  f0 = np.atleast_1d(f0)
484
551
  if f0.ndim > 1:
@@ -491,7 +558,7 @@ def approx_derivative(fun, x0, method='3-point', rel_step=None, abs_step=None,
491
558
  if rel_step is None:
492
559
  rel_step = _eps_for_method(x0.dtype, f0.dtype, method)
493
560
 
494
- return _linear_operator_difference(fun_wrapped, x0,
561
+ J, _ = _linear_operator_difference(fun_wrapped, x0,
495
562
  f0, rel_step, method)
496
563
  else:
497
564
  # by default we use rel_step
@@ -519,25 +586,35 @@ def approx_derivative(fun, x0, method='3-point', rel_step=None, abs_step=None,
519
586
  elif method == 'cs':
520
587
  use_one_sided = False
521
588
 
522
- if sparsity is None:
523
- return _dense_difference(fun_wrapped, x0, f0, h,
524
- use_one_sided, method)
525
- else:
526
- if not issparse(sparsity) and len(sparsity) == 2:
527
- structure, groups = sparsity
589
+ # normalize workers
590
+ workers = workers or map
591
+ with MapWrapper(workers) as mf:
592
+ if sparsity is None:
593
+ J, _nfev = _dense_difference(fun_wrapped, x0, f0, h,
594
+ use_one_sided, method,
595
+ mf)
528
596
  else:
529
- structure = sparsity
530
- groups = group_columns(sparsity)
531
-
532
- if issparse(structure):
533
- structure = csc_matrix(structure)
534
- else:
535
- structure = np.atleast_2d(structure)
536
-
537
- groups = np.atleast_1d(groups)
538
- return _sparse_difference(fun_wrapped, x0, f0, h,
539
- use_one_sided, structure,
540
- groups, method)
597
+ if not issparse(sparsity) and len(sparsity) == 2:
598
+ structure, groups = sparsity
599
+ else:
600
+ structure = sparsity
601
+ groups = group_columns(sparsity)
602
+
603
+ if issparse(structure):
604
+ structure = structure.tocsc()
605
+ else:
606
+ structure = np.atleast_2d(structure)
607
+ groups = np.atleast_1d(groups)
608
+ J, _nfev = _sparse_difference(fun_wrapped, x0, f0, h,
609
+ use_one_sided, structure,
610
+ groups, method, mf)
611
+
612
+ if full_output:
613
+ nfev += _nfev
614
+ info_dict["nfev"] = nfev
615
+ return J, info_dict
616
+ else:
617
+ return J
541
618
 
542
619
 
543
620
  def _linear_operator_difference(fun, x0, f0, h, method):
@@ -545,6 +622,7 @@ def _linear_operator_difference(fun, x0, f0, h, method):
545
622
  n = x0.size
546
623
 
547
624
  if method == '2-point':
625
+ # nfev = 1
548
626
  def matvec(p):
549
627
  if np.array_equal(p, np.zeros_like(p)):
550
628
  return np.zeros(m)
@@ -554,6 +632,7 @@ def _linear_operator_difference(fun, x0, f0, h, method):
554
632
  return df / dx
555
633
 
556
634
  elif method == '3-point':
635
+ # nfev = 2
557
636
  def matvec(p):
558
637
  if np.array_equal(p, np.zeros_like(p)):
559
638
  return np.zeros(m)
@@ -566,6 +645,7 @@ def _linear_operator_difference(fun, x0, f0, h, method):
566
645
  return df / dx
567
646
 
568
647
  elif method == 'cs':
648
+ # nfev = 1
569
649
  def matvec(p):
570
650
  if np.array_equal(p, np.zeros_like(p)):
571
651
  return np.zeros(m)
@@ -574,59 +654,97 @@ def _linear_operator_difference(fun, x0, f0, h, method):
574
654
  f1 = fun(x)
575
655
  df = f1.imag
576
656
  return df / dx
577
-
578
657
  else:
579
658
  raise RuntimeError("Never be here.")
580
659
 
581
- return LinearOperator((m, n), matvec)
660
+ return LinearOperator((m, n), matvec), 0
582
661
 
583
662
 
584
- def _dense_difference(fun, x0, f0, h, use_one_sided, method):
663
+ def _dense_difference(fun, x0, f0, h, use_one_sided, method, workers):
585
664
  m = f0.size
586
665
  n = x0.size
587
666
  J_transposed = np.empty((n, m))
588
- x1 = x0.copy()
589
- x2 = x0.copy()
590
- xc = x0.astype(complex, copy=True)
667
+ nfev = 0
591
668
 
592
- for i in range(h.size):
593
- if method == '2-point':
594
- x1[i] += h[i]
595
- dx = x1[i] - x0[i] # Recompute dx as exactly representable number.
596
- df = fun(x1) - f0
597
- elif method == '3-point' and use_one_sided[i]:
598
- x1[i] += h[i]
599
- x2[i] += 2 * h[i]
600
- dx = x2[i] - x0[i]
601
- f1 = fun(x1)
602
- f2 = fun(x2)
603
- df = -3.0 * f0 + 4 * f1 - f2
604
- elif method == '3-point' and not use_one_sided[i]:
605
- x1[i] -= h[i]
606
- x2[i] += h[i]
607
- dx = x2[i] - x1[i]
608
- f1 = fun(x1)
609
- f2 = fun(x2)
610
- df = f2 - f1
611
- elif method == 'cs':
612
- xc[i] += h[i] * 1.j
613
- f1 = fun(xc)
614
- df = f1.imag
615
- dx = h[i]
616
- else:
617
- raise RuntimeError("Never be here.")
669
+ if method == '2-point':
670
+ def x_generator2(x0, h):
671
+ for i in range(n):
672
+ # If copying isn't done then it's possible for different workers
673
+ # to see the same values of x1. (At least that's what happened
674
+ # when I used `multiprocessing.dummy.Pool`).
675
+ # I also considered creating all the vectors at once, but that
676
+ # means assembling a very large N x N array. It's therefore a
677
+ # trade-off between N array copies or creating an NxN array.
678
+ x1 = np.copy(x0)
679
+ x1[i] = x0[i] + h[i]
680
+ yield x1
681
+
682
+ # only f_evals (numerator) needs parallelization, the denominator
683
+ # (the step size) is fast to calculate.
684
+ f_evals = workers(fun, x_generator2(x0, h))
685
+ dx = [(x0[i] + h[i]) - x0[i] for i in range(n)]
686
+ df = [f_eval - f0 for f_eval in f_evals]
687
+ df_dx = [delf / delx for delf, delx in zip(df, dx)]
688
+ nfev += len(df_dx)
618
689
 
619
- J_transposed[i] = df / dx
620
- x1[i] = x2[i] = xc[i] = x0[i]
690
+ elif method == '3-point':
691
+ def x_generator3(x0, h, use_one_sided):
692
+ for i, one_sided in enumerate(use_one_sided):
693
+ x1 = np.copy(x0)
694
+ x2 = np.copy(x0)
695
+ if one_sided:
696
+ x1[i] = x0[i] + h[i]
697
+ x2[i] = x0[i] + 2*h[i]
698
+ else:
699
+ x1[i] = x0[i] - h[i]
700
+ x2[i] = x0[i] + h[i]
701
+ yield x1
702
+ yield x2
703
+
704
+ # workers may return something like a list that needs to be turned
705
+ # into an iterable (can't call `next` on a list)
706
+ f_evals = iter(workers(fun, x_generator3(x0, h, use_one_sided)))
707
+ gen = x_generator3(x0, h, use_one_sided)
708
+ dx = list()
709
+ df = list()
710
+ for i, one_sided in enumerate(use_one_sided):
711
+ l = next(gen)
712
+ u = next(gen)
713
+
714
+ f1 = next(f_evals)
715
+ f2 = next(f_evals)
716
+ if one_sided:
717
+ dx.append(u[i] - x0[i])
718
+ df.append(-3.0 * f0 + 4 * f1 - f2)
719
+ else:
720
+ dx.append(u[i] - l[i])
721
+ df.append(f2 - f1)
722
+ df_dx = [delf / delx for delf, delx in zip(df, dx)]
723
+ nfev += 2 * len(df_dx)
724
+ elif method == 'cs':
725
+ def x_generator_cs(x0, h):
726
+ for i in range(n):
727
+ xc = x0.astype(complex, copy=True)
728
+ xc[i] += h[i] * 1.j
729
+ yield xc
730
+
731
+ f_evals = iter(workers(fun, x_generator_cs(x0, h)))
732
+ df_dx = [f1.imag / hi for f1, hi in zip(f_evals, h)]
733
+ nfev += len(df_dx)
734
+ else:
735
+ raise RuntimeError("Never be here.")
736
+
737
+ for i, v in enumerate(df_dx):
738
+ J_transposed[i] = v
621
739
 
622
740
  if m == 1:
623
741
  J_transposed = np.ravel(J_transposed)
624
742
 
625
- return J_transposed.T
743
+ return J_transposed.T, nfev
626
744
 
627
745
 
628
746
  def _sparse_difference(fun, x0, f0, h, use_one_sided,
629
- structure, groups, method):
747
+ structure, groups, method, workers):
630
748
  m = f0.size
631
749
  n = x0.size
632
750
  row_indices = []
@@ -634,24 +752,24 @@ def _sparse_difference(fun, x0, f0, h, use_one_sided,
634
752
  fractions = []
635
753
 
636
754
  n_groups = np.max(groups) + 1
637
- for group in range(n_groups):
755
+ nfev = 0
756
+
757
+ def e_generator():
638
758
  # Perturb variables which are in the same group simultaneously.
639
- e = np.equal(group, groups)
640
- h_vec = h * e
641
- if method == '2-point':
759
+ for group in range(n_groups):
760
+ yield np.equal(group, groups)
761
+
762
+ def x_generator2():
763
+ e_gen = e_generator()
764
+ for e in e_gen:
765
+ h_vec = h * e
642
766
  x = x0 + h_vec
643
- dx = x - x0
644
- df = fun(x) - f0
645
- # The result is written to columns which correspond to perturbed
646
- # variables.
647
- cols, = np.nonzero(e)
648
- # Find all non-zero elements in selected columns of Jacobian.
649
- i, j, _ = find(structure[:, cols])
650
- # Restore column indices in the full array.
651
- j = cols[j]
652
- elif method == '3-point':
653
- # Here we do conceptually the same but separate one-sided
654
- # and two-sided schemes.
767
+ yield x
768
+
769
+ def x_generator3():
770
+ e_gen = e_generator()
771
+ for e in e_gen:
772
+ h_vec = h * e
655
773
  x1 = x0.copy()
656
774
  x2 = x0.copy()
657
775
 
@@ -662,17 +780,54 @@ def _sparse_difference(fun, x0, f0, h, use_one_sided,
662
780
  mask_2 = ~use_one_sided & e
663
781
  x1[mask_2] -= h_vec[mask_2]
664
782
  x2[mask_2] += h_vec[mask_2]
783
+ yield x1
784
+ yield x2
785
+
786
+ def x_generator_cs():
787
+ e_gen = e_generator()
788
+ for e in e_gen:
789
+ h_vec = h * e
790
+ yield x0 + h_vec * 1.j
791
+
792
+ # evaluate the function for each of the groups
793
+ if method == '2-point':
794
+ f_evals = iter(workers(fun, x_generator2()))
795
+ xs = x_generator2()
796
+ elif method == '3-point':
797
+ f_evals = iter(workers(fun, x_generator3()))
798
+ xs = x_generator3()
799
+ elif method == 'cs':
800
+ f_evals = iter(workers(fun, x_generator_cs()))
801
+
802
+ for e in e_generator():
803
+ # The result is written to columns which correspond to perturbed
804
+ # variables.
805
+ cols, = np.nonzero(e)
806
+ # Find all non-zero elements in selected columns of Jacobian.
807
+ i, j, _ = find(structure[:, cols])
808
+ # Restore column indices in the full array.
809
+ j = cols[j]
810
+
811
+ if method == '2-point':
812
+ dx = next(xs) - x0
813
+ df = next(f_evals) - f0
814
+ nfev += 1
815
+ elif method == '3-point':
816
+ # Here we do conceptually the same but separate one-sided
817
+ # and two-sided schemes.
818
+ x1 = next(xs)
819
+ x2 = next(xs)
820
+
821
+ mask_1 = use_one_sided & e
822
+ mask_2 = ~use_one_sided & e
665
823
 
666
824
  dx = np.zeros(n)
667
825
  dx[mask_1] = x2[mask_1] - x0[mask_1]
668
826
  dx[mask_2] = x2[mask_2] - x1[mask_2]
669
827
 
670
- f1 = fun(x1)
671
- f2 = fun(x2)
672
-
673
- cols, = np.nonzero(e)
674
- i, j, _ = find(structure[:, cols])
675
- j = cols[j]
828
+ f1 = next(f_evals)
829
+ f2 = next(f_evals)
830
+ nfev += 2
676
831
 
677
832
  mask = use_one_sided[j]
678
833
  df = np.empty(m)
@@ -683,17 +838,15 @@ def _sparse_difference(fun, x0, f0, h, use_one_sided,
683
838
  rows = i[~mask]
684
839
  df[rows] = f2[rows] - f1[rows]
685
840
  elif method == 'cs':
686
- f1 = fun(x0 + h_vec*1.j)
841
+ f1 = next(f_evals)
842
+ nfev += 1
687
843
  df = f1.imag
688
- dx = h_vec
689
- cols, = np.nonzero(e)
690
- i, j, _ = find(structure[:, cols])
691
- j = cols[j]
844
+ dx = h * e
692
845
  else:
693
846
  raise ValueError("Never be here.")
694
847
 
695
848
  # All that's left is to compute the fraction. We store i, j and
696
- # fractions as separate arrays and later construct coo_matrix.
849
+ # fractions as separate arrays and later construct csr_array.
697
850
  row_indices.append(i)
698
851
  col_indices.append(j)
699
852
  fractions.append(df[i] / dx[j])
@@ -701,8 +854,33 @@ def _sparse_difference(fun, x0, f0, h, use_one_sided,
701
854
  row_indices = np.hstack(row_indices)
702
855
  col_indices = np.hstack(col_indices)
703
856
  fractions = np.hstack(fractions)
704
- J = coo_matrix((fractions, (row_indices, col_indices)), shape=(m, n))
705
- return csr_matrix(J)
857
+
858
+ if isspmatrix(structure):
859
+ return csr_matrix((fractions, (row_indices, col_indices)), shape=(m, n)), nfev
860
+ return csr_array((fractions, (row_indices, col_indices)), shape=(m, n)), nfev
861
+
862
+
863
+ class _Fun_Wrapper:
864
+ # Permits pickling of a wrapped function
865
+ def __init__(self, fun, x0, args, kwargs):
866
+ self.fun = fun
867
+ self.x0 = x0
868
+ self.args = args
869
+ self.kwargs = kwargs
870
+
871
+ def __call__(self, x):
872
+ # send user function same fp type as x0. (but only if cs is not being
873
+ # used
874
+ xp = array_namespace(self.x0)
875
+
876
+ if xp.isdtype(x.dtype, "real floating"):
877
+ x = xp.astype(x, self.x0.dtype)
878
+
879
+ f = np.atleast_1d(self.fun(x, *self.args, **self.kwargs))
880
+ if f.ndim > 1:
881
+ raise RuntimeError("`fun` return value has "
882
+ "more than 1 dimension.")
883
+ return f
706
884
 
707
885
 
708
886
  def check_derivative(fun, jac, x0, bounds=(-np.inf, np.inf), args=(),
@@ -719,7 +897,7 @@ def check_derivative(fun, jac, x0, bounds=(-np.inf, np.inf), args=(),
719
897
  jac : callable
720
898
  Function which computes Jacobian matrix of `fun`. It must work with
721
899
  argument x the same way as `fun`. The return value must be array_like
722
- or sparse matrix with an appropriate shape.
900
+ or sparse array with an appropriate shape.
723
901
  x0 : array_like of shape (n,) or float
724
902
  Point at which to estimate the derivatives. Float will be converted
725
903
  to 1-D array.
@@ -772,7 +950,7 @@ def check_derivative(fun, jac, x0, bounds=(-np.inf, np.inf), args=(),
772
950
  if issparse(J_to_test):
773
951
  J_diff = approx_derivative(fun, x0, bounds=bounds, sparsity=J_to_test,
774
952
  args=args, kwargs=kwargs)
775
- J_to_test = csr_matrix(J_to_test)
953
+ J_to_test = csr_array(J_to_test)
776
954
  abs_err = J_to_test - J_diff
777
955
  i, j, abs_err_data = find(abs_err)
778
956
  J_diff_data = np.asarray(J_diff[i, j]).ravel()