scipy 1.15.3__cp313-cp313-macosx_12_0_arm64.whl → 1.16.0rc2__cp313-cp313-macosx_12_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (629) 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-313-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-313-darwin.so +0 -0
  9. scipy/_lib/_docscrape.py +1 -1
  10. scipy/_lib/_elementwise_iterative_method.py +15 -26
  11. scipy/_lib/_sparse.py +41 -0
  12. scipy/_lib/_test_deprecation_call.cpython-313-darwin.so +0 -0
  13. scipy/_lib/_test_deprecation_def.cpython-313-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-313-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-313-darwin.so +0 -0
  95. scipy/cluster/_optimal_leaf_ordering.cpython-313-darwin.so +0 -0
  96. scipy/cluster/_vq.cpython-313-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 +263 -157
  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-313-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-313-darwin.so +0 -0
  126. scipy/integrate/_lsoda.cpython-313-darwin.so +0 -0
  127. scipy/integrate/_ode.py +9 -2
  128. scipy/integrate/_odepack.cpython-313-darwin.so +0 -0
  129. scipy/integrate/_quad_vec.py +21 -29
  130. scipy/integrate/_quadpack.cpython-313-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-313-darwin.so +0 -0
  136. scipy/integrate/_vode.cpython-313-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-313-darwin.so +0 -0
  147. scipy/interpolate/_dierckx.cpython-313-darwin.so +0 -0
  148. scipy/interpolate/_fitpack.cpython-313-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-313-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-313-darwin.so +0 -0
  158. scipy/interpolate/_rbf.py +2 -2
  159. scipy/interpolate/_rbfinterp.py +1 -1
  160. scipy/interpolate/_rbfinterp_pythran.cpython-313-darwin.so +0 -0
  161. scipy/interpolate/_rgi.py +31 -26
  162. scipy/interpolate/_rgi_cython.cpython-313-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-313-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-313-darwin.so +0 -0
  182. scipy/io/matlab/_mio_utils.cpython-313-darwin.so +0 -0
  183. scipy/io/matlab/_miobase.py +4 -1
  184. scipy/io/matlab/_streams.cpython-313-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-313-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-313-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-313-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-313-darwin.so +0 -0
  205. scipy/linalg/_expm_frechet.py +4 -0
  206. scipy/linalg/_fblas.cpython-313-darwin.so +0 -0
  207. scipy/linalg/_flapack.cpython-313-darwin.so +0 -0
  208. scipy/linalg/_linalg_pythran.cpython-313-darwin.so +0 -0
  209. scipy/linalg/_matfuncs.py +187 -4
  210. scipy/linalg/_matfuncs_expm.cpython-313-darwin.so +0 -0
  211. scipy/linalg/_matfuncs_schur_sqrtm.cpython-313-darwin.so +0 -0
  212. scipy/linalg/_matfuncs_sqrtm.py +1 -99
  213. scipy/linalg/_matfuncs_sqrtm_triu.cpython-313-darwin.so +0 -0
  214. scipy/linalg/_procrustes.py +2 -0
  215. scipy/linalg/_sketches.py +17 -6
  216. scipy/linalg/_solve_toeplitz.cpython-313-darwin.so +0 -0
  217. scipy/linalg/_solvers.py +7 -2
  218. scipy/linalg/_special_matrices.py +26 -36
  219. scipy/linalg/cython_blas.cpython-313-darwin.so +0 -0
  220. scipy/linalg/cython_lapack.cpython-313-darwin.so +0 -0
  221. scipy/linalg/lapack.py +22 -2
  222. scipy/linalg/tests/_cython_examples/meson.build +7 -0
  223. scipy/linalg/tests/test_basic.py +31 -16
  224. scipy/linalg/tests/test_batch.py +588 -0
  225. scipy/linalg/tests/test_cythonized_array_utils.py +0 -2
  226. scipy/linalg/tests/test_decomp.py +40 -3
  227. scipy/linalg/tests/test_decomp_cossin.py +14 -0
  228. scipy/linalg/tests/test_decomp_ldl.py +1 -1
  229. scipy/linalg/tests/test_lapack.py +115 -7
  230. scipy/linalg/tests/test_matfuncs.py +157 -102
  231. scipy/linalg/tests/test_procrustes.py +0 -7
  232. scipy/linalg/tests/test_solve_toeplitz.py +1 -1
  233. scipy/linalg/tests/test_special_matrices.py +1 -5
  234. scipy/ndimage/__init__.py +1 -0
  235. scipy/ndimage/_cytest.cpython-313-darwin.so +0 -0
  236. scipy/ndimage/_delegators.py +8 -2
  237. scipy/ndimage/_filters.py +453 -5
  238. scipy/ndimage/_interpolation.py +36 -6
  239. scipy/ndimage/_measurements.py +4 -2
  240. scipy/ndimage/_morphology.py +5 -0
  241. scipy/ndimage/_nd_image.cpython-313-darwin.so +0 -0
  242. scipy/ndimage/_ni_docstrings.py +5 -1
  243. scipy/ndimage/_ni_label.cpython-313-darwin.so +0 -0
  244. scipy/ndimage/_ni_support.py +1 -5
  245. scipy/ndimage/_rank_filter_1d.cpython-313-darwin.so +0 -0
  246. scipy/ndimage/_support_alternative_backends.py +18 -6
  247. scipy/ndimage/tests/test_filters.py +370 -259
  248. scipy/ndimage/tests/test_fourier.py +7 -9
  249. scipy/ndimage/tests/test_interpolation.py +68 -61
  250. scipy/ndimage/tests/test_measurements.py +18 -35
  251. scipy/ndimage/tests/test_morphology.py +143 -131
  252. scipy/ndimage/tests/test_splines.py +1 -3
  253. scipy/odr/__odrpack.cpython-313-darwin.so +0 -0
  254. scipy/optimize/_basinhopping.py +13 -7
  255. scipy/optimize/_bglu_dense.cpython-313-darwin.so +0 -0
  256. scipy/optimize/_bracket.py +17 -24
  257. scipy/optimize/_chandrupatla.py +9 -10
  258. scipy/optimize/_cobyla_py.py +104 -123
  259. scipy/optimize/_constraints.py +14 -10
  260. scipy/optimize/_differentiable_functions.py +371 -230
  261. scipy/optimize/_differentialevolution.py +4 -3
  262. scipy/optimize/_direct.cpython-313-darwin.so +0 -0
  263. scipy/optimize/_dual_annealing.py +1 -1
  264. scipy/optimize/_elementwise.py +1 -4
  265. scipy/optimize/_group_columns.cpython-313-darwin.so +0 -0
  266. scipy/optimize/_lbfgsb.cpython-313-darwin.so +0 -0
  267. scipy/optimize/_lbfgsb_py.py +57 -16
  268. scipy/optimize/_linprog_doc.py +2 -2
  269. scipy/optimize/_linprog_highs.py +2 -2
  270. scipy/optimize/_linprog_ip.py +25 -10
  271. scipy/optimize/_linprog_util.py +14 -16
  272. scipy/optimize/_lsap.cpython-313-darwin.so +0 -0
  273. scipy/optimize/_lsq/common.py +3 -3
  274. scipy/optimize/_lsq/dogbox.py +16 -2
  275. scipy/optimize/_lsq/givens_elimination.cpython-313-darwin.so +0 -0
  276. scipy/optimize/_lsq/least_squares.py +198 -126
  277. scipy/optimize/_lsq/lsq_linear.py +6 -6
  278. scipy/optimize/_lsq/trf.py +35 -8
  279. scipy/optimize/_milp.py +3 -1
  280. scipy/optimize/_minimize.py +105 -36
  281. scipy/optimize/_minpack.cpython-313-darwin.so +0 -0
  282. scipy/optimize/_minpack_py.py +21 -14
  283. scipy/optimize/_moduleTNC.cpython-313-darwin.so +0 -0
  284. scipy/optimize/_nnls.py +20 -21
  285. scipy/optimize/_nonlin.py +34 -3
  286. scipy/optimize/_numdiff.py +288 -110
  287. scipy/optimize/_optimize.py +86 -48
  288. scipy/optimize/_pava_pybind.cpython-313-darwin.so +0 -0
  289. scipy/optimize/_remove_redundancy.py +5 -5
  290. scipy/optimize/_root_scalar.py +1 -1
  291. scipy/optimize/_shgo.py +6 -0
  292. scipy/optimize/_shgo_lib/_complex.py +1 -1
  293. scipy/optimize/_slsqp_py.py +216 -124
  294. scipy/optimize/_slsqplib.cpython-313-darwin.so +0 -0
  295. scipy/optimize/_spectral.py +1 -1
  296. scipy/optimize/_tnc.py +8 -1
  297. scipy/optimize/_trlib/_trlib.cpython-313-darwin.so +0 -0
  298. scipy/optimize/_trustregion.py +20 -6
  299. scipy/optimize/_trustregion_constr/canonical_constraint.py +7 -7
  300. scipy/optimize/_trustregion_constr/equality_constrained_sqp.py +1 -1
  301. scipy/optimize/_trustregion_constr/minimize_trustregion_constr.py +11 -3
  302. scipy/optimize/_trustregion_constr/projections.py +12 -8
  303. scipy/optimize/_trustregion_constr/qp_subproblem.py +9 -9
  304. scipy/optimize/_trustregion_constr/tests/test_projections.py +7 -7
  305. scipy/optimize/_trustregion_constr/tests/test_qp_subproblem.py +77 -77
  306. scipy/optimize/_trustregion_constr/tr_interior_point.py +5 -5
  307. scipy/optimize/_trustregion_exact.py +0 -1
  308. scipy/optimize/_zeros.cpython-313-darwin.so +0 -0
  309. scipy/optimize/_zeros_py.py +97 -17
  310. scipy/optimize/cython_optimize/_zeros.cpython-313-darwin.so +0 -0
  311. scipy/optimize/slsqp.py +0 -1
  312. scipy/optimize/tests/test__basinhopping.py +1 -1
  313. scipy/optimize/tests/test__differential_evolution.py +4 -4
  314. scipy/optimize/tests/test__linprog_clean_inputs.py +5 -3
  315. scipy/optimize/tests/test__numdiff.py +66 -22
  316. scipy/optimize/tests/test__remove_redundancy.py +2 -2
  317. scipy/optimize/tests/test__shgo.py +9 -1
  318. scipy/optimize/tests/test_bracket.py +36 -46
  319. scipy/optimize/tests/test_chandrupatla.py +133 -135
  320. scipy/optimize/tests/test_cobyla.py +74 -45
  321. scipy/optimize/tests/test_constraints.py +1 -1
  322. scipy/optimize/tests/test_differentiable_functions.py +226 -6
  323. scipy/optimize/tests/test_lbfgsb_hessinv.py +22 -0
  324. scipy/optimize/tests/test_least_squares.py +125 -13
  325. scipy/optimize/tests/test_linear_assignment.py +3 -3
  326. scipy/optimize/tests/test_linprog.py +3 -3
  327. scipy/optimize/tests/test_lsq_linear.py +6 -6
  328. scipy/optimize/tests/test_minimize_constrained.py +2 -2
  329. scipy/optimize/tests/test_minpack.py +4 -4
  330. scipy/optimize/tests/test_nnls.py +43 -3
  331. scipy/optimize/tests/test_nonlin.py +36 -0
  332. scipy/optimize/tests/test_optimize.py +95 -17
  333. scipy/optimize/tests/test_slsqp.py +36 -4
  334. scipy/optimize/tests/test_zeros.py +34 -1
  335. scipy/signal/__init__.py +12 -23
  336. scipy/signal/_delegators.py +568 -0
  337. scipy/signal/_filter_design.py +459 -241
  338. scipy/signal/_fir_filter_design.py +262 -90
  339. scipy/signal/_lti_conversion.py +3 -2
  340. scipy/signal/_ltisys.py +118 -91
  341. scipy/signal/_max_len_seq_inner.cpython-313-darwin.so +0 -0
  342. scipy/signal/_peak_finding_utils.cpython-313-darwin.so +0 -0
  343. scipy/signal/_polyutils.py +172 -0
  344. scipy/signal/_short_time_fft.py +519 -70
  345. scipy/signal/_signal_api.py +30 -0
  346. scipy/signal/_signaltools.py +719 -399
  347. scipy/signal/_sigtools.cpython-313-darwin.so +0 -0
  348. scipy/signal/_sosfilt.cpython-313-darwin.so +0 -0
  349. scipy/signal/_spectral_py.py +230 -50
  350. scipy/signal/_spline.cpython-313-darwin.so +0 -0
  351. scipy/signal/_spline_filters.py +108 -68
  352. scipy/signal/_support_alternative_backends.py +73 -0
  353. scipy/signal/_upfirdn.py +4 -1
  354. scipy/signal/_upfirdn_apply.cpython-313-darwin.so +0 -0
  355. scipy/signal/_waveforms.py +2 -11
  356. scipy/signal/_wavelets.py +1 -1
  357. scipy/signal/fir_filter_design.py +1 -0
  358. scipy/signal/spline.py +4 -11
  359. scipy/signal/tests/_scipy_spectral_test_shim.py +2 -171
  360. scipy/signal/tests/test_bsplines.py +114 -79
  361. scipy/signal/tests/test_cont2discrete.py +9 -2
  362. scipy/signal/tests/test_filter_design.py +721 -481
  363. scipy/signal/tests/test_fir_filter_design.py +332 -140
  364. scipy/signal/tests/test_savitzky_golay.py +4 -3
  365. scipy/signal/tests/test_short_time_fft.py +221 -3
  366. scipy/signal/tests/test_signaltools.py +2144 -1348
  367. scipy/signal/tests/test_spectral.py +50 -6
  368. scipy/signal/tests/test_splines.py +161 -96
  369. scipy/signal/tests/test_upfirdn.py +84 -50
  370. scipy/signal/tests/test_waveforms.py +20 -0
  371. scipy/signal/tests/test_windows.py +607 -466
  372. scipy/signal/windows/_windows.py +287 -148
  373. scipy/sparse/__init__.py +23 -4
  374. scipy/sparse/_base.py +270 -108
  375. scipy/sparse/_bsr.py +7 -4
  376. scipy/sparse/_compressed.py +59 -231
  377. scipy/sparse/_construct.py +90 -38
  378. scipy/sparse/_coo.py +115 -181
  379. scipy/sparse/_csc.py +4 -4
  380. scipy/sparse/_csparsetools.cpython-313-darwin.so +0 -0
  381. scipy/sparse/_csr.py +2 -2
  382. scipy/sparse/_data.py +48 -48
  383. scipy/sparse/_dia.py +105 -18
  384. scipy/sparse/_dok.py +0 -23
  385. scipy/sparse/_index.py +4 -4
  386. scipy/sparse/_matrix.py +23 -0
  387. scipy/sparse/_sparsetools.cpython-313-darwin.so +0 -0
  388. scipy/sparse/_sputils.py +37 -22
  389. scipy/sparse/base.py +0 -9
  390. scipy/sparse/bsr.py +0 -14
  391. scipy/sparse/compressed.py +0 -23
  392. scipy/sparse/construct.py +0 -6
  393. scipy/sparse/coo.py +0 -14
  394. scipy/sparse/csc.py +0 -3
  395. scipy/sparse/csgraph/_flow.cpython-313-darwin.so +0 -0
  396. scipy/sparse/csgraph/_matching.cpython-313-darwin.so +0 -0
  397. scipy/sparse/csgraph/_min_spanning_tree.cpython-313-darwin.so +0 -0
  398. scipy/sparse/csgraph/_reordering.cpython-313-darwin.so +0 -0
  399. scipy/sparse/csgraph/_shortest_path.cpython-313-darwin.so +0 -0
  400. scipy/sparse/csgraph/_tools.cpython-313-darwin.so +0 -0
  401. scipy/sparse/csgraph/_traversal.cpython-313-darwin.so +0 -0
  402. scipy/sparse/csgraph/tests/test_matching.py +14 -2
  403. scipy/sparse/csgraph/tests/test_pydata_sparse.py +4 -1
  404. scipy/sparse/csgraph/tests/test_shortest_path.py +83 -27
  405. scipy/sparse/csr.py +0 -5
  406. scipy/sparse/data.py +1 -6
  407. scipy/sparse/dia.py +0 -7
  408. scipy/sparse/dok.py +0 -10
  409. scipy/sparse/linalg/_dsolve/_superlu.cpython-313-darwin.so +0 -0
  410. scipy/sparse/linalg/_dsolve/linsolve.py +9 -0
  411. scipy/sparse/linalg/_dsolve/tests/test_linsolve.py +35 -28
  412. scipy/sparse/linalg/_eigen/arpack/_arpack.cpython-313-darwin.so +0 -0
  413. scipy/sparse/linalg/_eigen/arpack/arpack.py +23 -17
  414. scipy/sparse/linalg/_eigen/lobpcg/lobpcg.py +6 -6
  415. scipy/sparse/linalg/_interface.py +17 -18
  416. scipy/sparse/linalg/_isolve/_gcrotmk.py +4 -4
  417. scipy/sparse/linalg/_isolve/iterative.py +51 -45
  418. scipy/sparse/linalg/_isolve/lgmres.py +6 -6
  419. scipy/sparse/linalg/_isolve/minres.py +5 -5
  420. scipy/sparse/linalg/_isolve/tfqmr.py +7 -7
  421. scipy/sparse/linalg/_isolve/utils.py +2 -8
  422. scipy/sparse/linalg/_matfuncs.py +1 -1
  423. scipy/sparse/linalg/_norm.py +1 -1
  424. scipy/sparse/linalg/_propack/_cpropack.cpython-313-darwin.so +0 -0
  425. scipy/sparse/linalg/_propack/_dpropack.cpython-313-darwin.so +0 -0
  426. scipy/sparse/linalg/_propack/_spropack.cpython-313-darwin.so +0 -0
  427. scipy/sparse/linalg/_propack/_zpropack.cpython-313-darwin.so +0 -0
  428. scipy/sparse/linalg/_special_sparse_arrays.py +39 -38
  429. scipy/sparse/linalg/tests/test_pydata_sparse.py +14 -0
  430. scipy/sparse/tests/test_arithmetic1d.py +5 -2
  431. scipy/sparse/tests/test_base.py +214 -42
  432. scipy/sparse/tests/test_common1d.py +7 -7
  433. scipy/sparse/tests/test_construct.py +1 -1
  434. scipy/sparse/tests/test_coo.py +272 -4
  435. scipy/sparse/tests/test_sparsetools.py +5 -0
  436. scipy/sparse/tests/test_sputils.py +36 -7
  437. scipy/spatial/_ckdtree.cpython-313-darwin.so +0 -0
  438. scipy/spatial/_distance_pybind.cpython-313-darwin.so +0 -0
  439. scipy/spatial/_distance_wrap.cpython-313-darwin.so +0 -0
  440. scipy/spatial/_hausdorff.cpython-313-darwin.so +0 -0
  441. scipy/spatial/_qhull.cpython-313-darwin.so +0 -0
  442. scipy/spatial/_voronoi.cpython-313-darwin.so +0 -0
  443. scipy/spatial/distance.py +49 -42
  444. scipy/spatial/tests/test_distance.py +15 -1
  445. scipy/spatial/tests/test_kdtree.py +1 -0
  446. scipy/spatial/tests/test_qhull.py +7 -2
  447. scipy/spatial/transform/__init__.py +5 -3
  448. scipy/spatial/transform/_rigid_transform.cpython-313-darwin.so +0 -0
  449. scipy/spatial/transform/_rotation.cpython-313-darwin.so +0 -0
  450. scipy/spatial/transform/tests/test_rigid_transform.py +1221 -0
  451. scipy/spatial/transform/tests/test_rotation.py +1213 -832
  452. scipy/spatial/transform/tests/test_rotation_groups.py +3 -3
  453. scipy/spatial/transform/tests/test_rotation_spline.py +29 -8
  454. scipy/special/__init__.py +1 -47
  455. scipy/special/_add_newdocs.py +34 -772
  456. scipy/special/_basic.py +22 -25
  457. scipy/special/_comb.cpython-313-darwin.so +0 -0
  458. scipy/special/_ellip_harm_2.cpython-313-darwin.so +0 -0
  459. scipy/special/_gufuncs.cpython-313-darwin.so +0 -0
  460. scipy/special/_logsumexp.py +67 -58
  461. scipy/special/_orthogonal.pyi +1 -1
  462. scipy/special/_specfun.cpython-313-darwin.so +0 -0
  463. scipy/special/_special_ufuncs.cpython-313-darwin.so +0 -0
  464. scipy/special/_spherical_bessel.py +4 -4
  465. scipy/special/_support_alternative_backends.py +212 -119
  466. scipy/special/_test_internal.cpython-313-darwin.so +0 -0
  467. scipy/special/_testutils.py +4 -4
  468. scipy/special/_ufuncs.cpython-313-darwin.so +0 -0
  469. scipy/special/_ufuncs.pyi +1 -0
  470. scipy/special/_ufuncs.pyx +215 -1400
  471. scipy/special/_ufuncs_cxx.cpython-313-darwin.so +0 -0
  472. scipy/special/_ufuncs_cxx.pxd +2 -15
  473. scipy/special/_ufuncs_cxx.pyx +5 -44
  474. scipy/special/_ufuncs_cxx_defs.h +2 -16
  475. scipy/special/_ufuncs_defs.h +0 -8
  476. scipy/special/cython_special.cpython-313-darwin.so +0 -0
  477. scipy/special/cython_special.pxd +1 -1
  478. scipy/special/tests/_cython_examples/meson.build +10 -1
  479. scipy/special/tests/test_basic.py +153 -20
  480. scipy/special/tests/test_boost_ufuncs.py +3 -0
  481. scipy/special/tests/test_cdflib.py +35 -11
  482. scipy/special/tests/test_gammainc.py +16 -0
  483. scipy/special/tests/test_hyp2f1.py +2 -2
  484. scipy/special/tests/test_log1mexp.py +85 -0
  485. scipy/special/tests/test_logsumexp.py +206 -64
  486. scipy/special/tests/test_mpmath.py +1 -0
  487. scipy/special/tests/test_nan_inputs.py +1 -1
  488. scipy/special/tests/test_orthogonal.py +17 -18
  489. scipy/special/tests/test_sf_error.py +3 -2
  490. scipy/special/tests/test_sph_harm.py +6 -7
  491. scipy/special/tests/test_support_alternative_backends.py +211 -76
  492. scipy/stats/__init__.py +4 -1
  493. scipy/stats/_ansari_swilk_statistics.cpython-313-darwin.so +0 -0
  494. scipy/stats/_axis_nan_policy.py +5 -12
  495. scipy/stats/_biasedurn.cpython-313-darwin.so +0 -0
  496. scipy/stats/_continued_fraction.py +387 -0
  497. scipy/stats/_continuous_distns.py +277 -310
  498. scipy/stats/_correlation.py +1 -1
  499. scipy/stats/_covariance.py +6 -3
  500. scipy/stats/_discrete_distns.py +39 -32
  501. scipy/stats/_distn_infrastructure.py +39 -12
  502. scipy/stats/_distribution_infrastructure.py +900 -238
  503. scipy/stats/_entropy.py +9 -10
  504. scipy/{_lib → stats}/_finite_differences.py +1 -1
  505. scipy/stats/_hypotests.py +83 -50
  506. scipy/stats/_kde.py +53 -49
  507. scipy/stats/_ksstats.py +1 -1
  508. scipy/stats/_levy_stable/__init__.py +7 -15
  509. scipy/stats/_levy_stable/levyst.cpython-313-darwin.so +0 -0
  510. scipy/stats/_morestats.py +118 -73
  511. scipy/stats/_mstats_basic.py +13 -17
  512. scipy/stats/_mstats_extras.py +8 -8
  513. scipy/stats/_multivariate.py +89 -113
  514. scipy/stats/_new_distributions.py +97 -20
  515. scipy/stats/_page_trend_test.py +12 -5
  516. scipy/stats/_probability_distribution.py +265 -43
  517. scipy/stats/_qmc.py +14 -9
  518. scipy/stats/_qmc_cy.cpython-313-darwin.so +0 -0
  519. scipy/stats/_qmvnt.py +16 -95
  520. scipy/stats/_qmvnt_cy.cpython-313-darwin.so +0 -0
  521. scipy/stats/_quantile.py +335 -0
  522. scipy/stats/_rcont/rcont.cpython-313-darwin.so +0 -0
  523. scipy/stats/_resampling.py +4 -29
  524. scipy/stats/_sampling.py +1 -1
  525. scipy/stats/_sobol.cpython-313-darwin.so +0 -0
  526. scipy/stats/_stats.cpython-313-darwin.so +0 -0
  527. scipy/stats/_stats_mstats_common.py +21 -2
  528. scipy/stats/_stats_py.py +550 -476
  529. scipy/stats/_stats_pythran.cpython-313-darwin.so +0 -0
  530. scipy/stats/_unuran/unuran_wrapper.cpython-313-darwin.so +0 -0
  531. scipy/stats/_unuran/unuran_wrapper.pyi +2 -1
  532. scipy/stats/_variation.py +6 -8
  533. scipy/stats/_wilcoxon.py +13 -7
  534. scipy/stats/tests/common_tests.py +6 -4
  535. scipy/stats/tests/test_axis_nan_policy.py +62 -24
  536. scipy/stats/tests/test_continued_fraction.py +173 -0
  537. scipy/stats/tests/test_continuous.py +379 -60
  538. scipy/stats/tests/test_continuous_basic.py +18 -12
  539. scipy/stats/tests/test_discrete_basic.py +14 -8
  540. scipy/stats/tests/test_discrete_distns.py +16 -16
  541. scipy/stats/tests/test_distributions.py +95 -75
  542. scipy/stats/tests/test_entropy.py +40 -48
  543. scipy/stats/tests/test_fit.py +4 -3
  544. scipy/stats/tests/test_hypotests.py +153 -24
  545. scipy/stats/tests/test_kdeoth.py +109 -41
  546. scipy/stats/tests/test_marray.py +289 -0
  547. scipy/stats/tests/test_morestats.py +79 -47
  548. scipy/stats/tests/test_mstats_basic.py +3 -3
  549. scipy/stats/tests/test_multivariate.py +434 -83
  550. scipy/stats/tests/test_qmc.py +13 -10
  551. scipy/stats/tests/test_quantile.py +199 -0
  552. scipy/stats/tests/test_rank.py +119 -112
  553. scipy/stats/tests/test_resampling.py +47 -56
  554. scipy/stats/tests/test_sampling.py +9 -4
  555. scipy/stats/tests/test_stats.py +799 -939
  556. scipy/stats/tests/test_variation.py +8 -6
  557. scipy/version.py +2 -2
  558. {scipy-1.15.3.dist-info → scipy-1.16.0rc2.dist-info}/LICENSE.txt +4 -4
  559. {scipy-1.15.3.dist-info → scipy-1.16.0rc2.dist-info}/METADATA +11 -11
  560. {scipy-1.15.3.dist-info → scipy-1.16.0rc2.dist-info}/RECORD +561 -568
  561. scipy-1.16.0rc2.dist-info/WHEEL +6 -0
  562. scipy/_lib/array_api_extra/_funcs.py +0 -484
  563. scipy/_lib/array_api_extra/_typing.py +0 -8
  564. scipy/interpolate/_bspl.cpython-313-darwin.so +0 -0
  565. scipy/optimize/_cobyla.cpython-313-darwin.so +0 -0
  566. scipy/optimize/_cython_nnls.cpython-313-darwin.so +0 -0
  567. scipy/optimize/_slsqp.cpython-313-darwin.so +0 -0
  568. scipy/spatial/qhull_src/COPYING.txt +0 -38
  569. scipy/special/libsf_error_state.dylib +0 -0
  570. scipy/special/tests/test_log_softmax.py +0 -109
  571. scipy/special/tests/test_xsf_cuda.py +0 -114
  572. scipy/special/xsf/binom.h +0 -89
  573. scipy/special/xsf/cdflib.h +0 -100
  574. scipy/special/xsf/cephes/airy.h +0 -307
  575. scipy/special/xsf/cephes/besselpoly.h +0 -51
  576. scipy/special/xsf/cephes/beta.h +0 -257
  577. scipy/special/xsf/cephes/cbrt.h +0 -131
  578. scipy/special/xsf/cephes/chbevl.h +0 -85
  579. scipy/special/xsf/cephes/chdtr.h +0 -193
  580. scipy/special/xsf/cephes/const.h +0 -87
  581. scipy/special/xsf/cephes/ellie.h +0 -293
  582. scipy/special/xsf/cephes/ellik.h +0 -251
  583. scipy/special/xsf/cephes/ellpe.h +0 -107
  584. scipy/special/xsf/cephes/ellpk.h +0 -117
  585. scipy/special/xsf/cephes/expn.h +0 -260
  586. scipy/special/xsf/cephes/gamma.h +0 -398
  587. scipy/special/xsf/cephes/hyp2f1.h +0 -596
  588. scipy/special/xsf/cephes/hyperg.h +0 -361
  589. scipy/special/xsf/cephes/i0.h +0 -149
  590. scipy/special/xsf/cephes/i1.h +0 -158
  591. scipy/special/xsf/cephes/igam.h +0 -421
  592. scipy/special/xsf/cephes/igam_asymp_coeff.h +0 -195
  593. scipy/special/xsf/cephes/igami.h +0 -313
  594. scipy/special/xsf/cephes/j0.h +0 -225
  595. scipy/special/xsf/cephes/j1.h +0 -198
  596. scipy/special/xsf/cephes/jv.h +0 -715
  597. scipy/special/xsf/cephes/k0.h +0 -164
  598. scipy/special/xsf/cephes/k1.h +0 -163
  599. scipy/special/xsf/cephes/kn.h +0 -243
  600. scipy/special/xsf/cephes/lanczos.h +0 -112
  601. scipy/special/xsf/cephes/ndtr.h +0 -275
  602. scipy/special/xsf/cephes/poch.h +0 -85
  603. scipy/special/xsf/cephes/polevl.h +0 -167
  604. scipy/special/xsf/cephes/psi.h +0 -194
  605. scipy/special/xsf/cephes/rgamma.h +0 -111
  606. scipy/special/xsf/cephes/scipy_iv.h +0 -811
  607. scipy/special/xsf/cephes/shichi.h +0 -248
  608. scipy/special/xsf/cephes/sici.h +0 -224
  609. scipy/special/xsf/cephes/sindg.h +0 -221
  610. scipy/special/xsf/cephes/tandg.h +0 -139
  611. scipy/special/xsf/cephes/trig.h +0 -58
  612. scipy/special/xsf/cephes/unity.h +0 -186
  613. scipy/special/xsf/cephes/zeta.h +0 -172
  614. scipy/special/xsf/config.h +0 -304
  615. scipy/special/xsf/digamma.h +0 -205
  616. scipy/special/xsf/error.h +0 -57
  617. scipy/special/xsf/evalpoly.h +0 -47
  618. scipy/special/xsf/expint.h +0 -266
  619. scipy/special/xsf/hyp2f1.h +0 -694
  620. scipy/special/xsf/iv_ratio.h +0 -173
  621. scipy/special/xsf/lambertw.h +0 -150
  622. scipy/special/xsf/loggamma.h +0 -163
  623. scipy/special/xsf/sici.h +0 -200
  624. scipy/special/xsf/tools.h +0 -427
  625. scipy/special/xsf/trig.h +0 -164
  626. scipy/special/xsf/wright_bessel.h +0 -843
  627. scipy/special/xsf/zlog1.h +0 -35
  628. scipy/stats/_mvn.cpython-313-darwin.so +0 -0
  629. scipy-1.15.3.dist-info/WHEEL +0 -4
@@ -1,91 +1,119 @@
1
+ from collections import namedtuple
2
+
1
3
  import numpy as np
2
4
  import scipy.sparse as sps
3
5
  from ._numdiff import approx_derivative, group_columns
4
6
  from ._hessian_update_strategy import HessianUpdateStrategy
5
7
  from scipy.sparse.linalg import LinearOperator
6
- from scipy._lib._array_api import array_namespace
8
+ from scipy._lib._array_api import array_namespace, xp_copy
7
9
  from scipy._lib import array_api_extra as xpx
10
+ from scipy._lib._util import _ScalarFunctionWrapper
8
11
 
9
12
 
10
13
  FD_METHODS = ('2-point', '3-point', 'cs')
11
14
 
12
15
 
13
- def _wrapper_fun(fun, args=()):
14
- ncalls = [0]
16
+ class _ScalarGradWrapper:
17
+ """
18
+ Wrapper class for gradient calculation
19
+ """
20
+ def __init__(
21
+ self,
22
+ grad,
23
+ fun=None,
24
+ args=None,
25
+ finite_diff_options=None,
26
+ ):
27
+ self.fun = fun
28
+ self.grad = grad
29
+ self.args = [] if args is None else args
30
+ self.finite_diff_options = finite_diff_options
31
+ self.ngev = 0
32
+ # number of function evaluations consumed by finite difference
33
+ self.nfev = 0
15
34
 
16
- def wrapped(x):
17
- ncalls[0] += 1
35
+ def __call__(self, x, f0=None, **kwds):
18
36
  # Send a copy because the user may overwrite it.
19
- # Overwriting results in undefined behaviour because
20
- # fun(self.x) will change self.x, with the two no longer linked.
21
- fx = fun(np.copy(x), *args)
22
- # Make sure the function returns a true scalar
23
- if not np.isscalar(fx):
24
- try:
25
- fx = np.asarray(fx).item()
26
- except (TypeError, ValueError) as e:
27
- raise ValueError(
28
- "The user-provided objective function "
29
- "must return a scalar value."
30
- ) from e
31
- return fx
32
- return wrapped, ncalls
33
-
34
-
35
- def _wrapper_grad(grad, fun=None, args=(), finite_diff_options=None):
36
- ncalls = [0]
37
-
38
- if callable(grad):
39
- def wrapped(x, **kwds):
40
- # kwds present to give function same signature as numdiff variant
41
- ncalls[0] += 1
42
- return np.atleast_1d(grad(np.copy(x), *args))
43
- return wrapped, ncalls
44
-
45
- elif grad in FD_METHODS:
46
- def wrapped1(x, f0=None):
47
- ncalls[0] += 1
48
- return approx_derivative(
49
- fun, x, f0=f0, **finite_diff_options
37
+ # The user of this class might want `x` to remain unchanged.
38
+ if callable(self.grad):
39
+ g = np.atleast_1d(self.grad(np.copy(x), *self.args))
40
+ elif self.grad in FD_METHODS:
41
+ g, dct = approx_derivative(
42
+ self.fun,
43
+ x,
44
+ f0=f0,
45
+ **self.finite_diff_options,
50
46
  )
47
+ self.nfev += dct['nfev']
51
48
 
52
- return wrapped1, ncalls
49
+ self.ngev += 1
50
+ return g
53
51
 
54
52
 
55
- def _wrapper_hess(hess, grad=None, x0=None, args=(), finite_diff_options=None):
56
- if callable(hess):
57
- H = hess(np.copy(x0), *args)
58
- ncalls = [1]
59
-
60
- if sps.issparse(H):
61
- def wrapped(x, **kwds):
62
- ncalls[0] += 1
63
- return sps.csr_matrix(hess(np.copy(x), *args))
53
+ class _ScalarHessWrapper:
54
+ """
55
+ Wrapper class for hess calculation via finite differences
56
+ """
57
+ def __init__(
58
+ self,
59
+ hess,
60
+ x0=None,
61
+ grad=None,
62
+ args=None,
63
+ finite_diff_options=None,
64
+ ):
65
+ self.hess = hess
66
+ self.grad = grad
67
+ self.args = [] if args is None else args
68
+ self.finite_diff_options = finite_diff_options
69
+ # keep track of any finite difference function evaluations for grad
70
+ self.ngev = 0
71
+ self.nhev = 0
72
+ self.H = None
73
+ self._hess_func = None
64
74
 
65
- H = sps.csr_matrix(H)
75
+ if callable(hess):
76
+ self.H = hess(np.copy(x0), *args)
77
+ self.nhev += 1
66
78
 
67
- elif isinstance(H, LinearOperator):
68
- def wrapped(x, **kwds):
69
- ncalls[0] += 1
70
- return hess(np.copy(x), *args)
79
+ if sps.issparse(self.H):
80
+ self._hess_func = self._sparse_callable
81
+ self.H = sps.csr_array(self.H)
82
+ elif isinstance(self.H, LinearOperator):
83
+ self._hess_func = self._linearoperator_callable
84
+ else:
85
+ # dense
86
+ self._hess_func = self._dense_callable
87
+ self.H = np.atleast_2d(np.asarray(self.H))
88
+ elif hess in FD_METHODS:
89
+ self._hess_func = self._fd_hess
71
90
 
72
- else: # dense
73
- def wrapped(x, **kwds):
74
- ncalls[0] += 1
75
- return np.atleast_2d(np.asarray(hess(np.copy(x), *args)))
91
+ def __call__(self, x, f0=None, **kwds):
92
+ return self._hess_func(np.copy(x), f0=f0)
76
93
 
77
- H = np.atleast_2d(np.asarray(H))
94
+ def _fd_hess(self, x, f0=None, **kwds):
95
+ self.H, dct = approx_derivative(
96
+ self.grad, x, f0=f0, **self.finite_diff_options
97
+ )
98
+ self.ngev += dct["nfev"]
99
+ return self.H
78
100
 
79
- return wrapped, ncalls, H
80
- elif hess in FD_METHODS:
81
- ncalls = [0]
101
+ def _sparse_callable(self, x, **kwds):
102
+ self.nhev += 1
103
+ self.H = sps.csr_array(self.hess(x, *self.args))
104
+ return self.H
82
105
 
83
- def wrapped1(x, f0=None):
84
- return approx_derivative(
85
- grad, x, f0=f0, **finite_diff_options
86
- )
106
+ def _dense_callable(self, x, **kwds):
107
+ self.nhev += 1
108
+ self.H = np.atleast_2d(
109
+ np.asarray(self.hess(x, *self.args))
110
+ )
111
+ return self.H
87
112
 
88
- return wrapped1, ncalls, None
113
+ def _linearoperator_callable(self, x, **kwds):
114
+ self.nhev += 1
115
+ self.H = self.hess(x, *self.args)
116
+ return self.H
89
117
 
90
118
 
91
119
  class ScalarFunction:
@@ -151,6 +179,21 @@ class ScalarFunction:
151
179
  For ``method='3-point'`` the sign of `epsilon` is ignored. By default
152
180
  relative steps are used, only if ``epsilon is not None`` are absolute
153
181
  steps used.
182
+ workers : map-like callable, optional
183
+ A map-like callable, such as `multiprocessing.Pool.map` for evaluating
184
+ any numerical differentiation in parallel.
185
+ This evaluation is carried out as ``workers(fun, iterable)``, or
186
+ ``workers(grad, iterable)``, depending on what is being numerically
187
+ differentiated.
188
+ Alternatively, if `workers` is an int the task is subdivided into `workers`
189
+ sections and the function evaluated in parallel
190
+ (uses `multiprocessing.Pool <multiprocessing>`).
191
+ Supply -1 to use all available CPU cores.
192
+ It is recommended that a map-like be used instead of int, as repeated
193
+ calls to `approx_derivative` will incur large overhead from setting up
194
+ new processes.
195
+
196
+ .. versionadded:: 1.16.0
154
197
 
155
198
  Notes
156
199
  -----
@@ -163,8 +206,9 @@ class ScalarFunction:
163
206
  will be set. However, a subsequent call with a different argument
164
207
  of *any* of the methods may overwrite the attribute.
165
208
  """
166
- def __init__(self, fun, x0, args, grad, hess, finite_diff_rel_step,
167
- finite_diff_bounds, epsilon=None):
209
+ def __init__(self, fun, x0, args, grad, hess, finite_diff_rel_step=None,
210
+ finite_diff_bounds=(-np.inf, np.inf), epsilon=None, workers=None):
211
+
168
212
  if not callable(grad) and grad not in FD_METHODS:
169
213
  raise ValueError(
170
214
  f"`grad` must be either callable or one of {FD_METHODS}."
@@ -182,7 +226,6 @@ class ScalarFunction:
182
226
  "finite-differences, we require the Hessian "
183
227
  "to be estimated using one of the "
184
228
  "quasi-Newton strategies.")
185
-
186
229
  self.xp = xp = array_namespace(x0)
187
230
  _x = xpx.atleast_nd(xp.asarray(x0), ndim=1, xp=xp)
188
231
  _dtype = xp.float64
@@ -190,7 +233,7 @@ class ScalarFunction:
190
233
  _dtype = _x.dtype
191
234
 
192
235
  # original arguments
193
- self._wrapped_fun, self._nfev = _wrapper_fun(fun, args=args)
236
+ self._wrapped_fun = _ScalarFunctionWrapper(fun, args)
194
237
  self._orig_fun = fun
195
238
  self._orig_grad = grad
196
239
  self._orig_hess = hess
@@ -207,65 +250,80 @@ class ScalarFunction:
207
250
  self._lowest_x = None
208
251
  self._lowest_f = np.inf
209
252
 
253
+ # normalize workers
254
+ workers = workers or map
255
+
210
256
  finite_diff_options = {}
211
257
  if grad in FD_METHODS:
212
258
  finite_diff_options["method"] = grad
213
259
  finite_diff_options["rel_step"] = finite_diff_rel_step
214
260
  finite_diff_options["abs_step"] = epsilon
215
261
  finite_diff_options["bounds"] = finite_diff_bounds
262
+ finite_diff_options["workers"] = workers
263
+ finite_diff_options["full_output"] = True
216
264
  if hess in FD_METHODS:
217
265
  finite_diff_options["method"] = hess
218
266
  finite_diff_options["rel_step"] = finite_diff_rel_step
219
267
  finite_diff_options["abs_step"] = epsilon
220
268
  finite_diff_options["as_linear_operator"] = True
269
+ finite_diff_options["workers"] = workers
270
+ finite_diff_options["full_output"] = True
221
271
 
222
272
  # Initial function evaluation
273
+ self._nfev = 0
223
274
  self._update_fun()
224
275
 
225
276
  # Initial gradient evaluation
226
- self._wrapped_grad, self._ngev = _wrapper_grad(
277
+ self._wrapped_grad = _ScalarGradWrapper(
227
278
  grad,
228
279
  fun=self._wrapped_fun,
229
280
  args=args,
230
- finite_diff_options=finite_diff_options
281
+ finite_diff_options=finite_diff_options,
231
282
  )
232
283
  self._update_grad()
233
284
 
234
285
  # Hessian evaluation
235
- if callable(hess):
236
- self._wrapped_hess, self._nhev, self.H = _wrapper_hess(
237
- hess, x0=x0, args=args
238
- )
239
- self.H_updated = True
240
- elif hess in FD_METHODS:
241
- self._wrapped_hess, self._nhev, self.H = _wrapper_hess(
242
- hess,
243
- grad=self._wrapped_grad,
244
- x0=x0,
245
- finite_diff_options=finite_diff_options
246
- )
247
- self._update_grad()
248
- self.H = self._wrapped_hess(self.x, f0=self.g)
249
- self.H_updated = True
250
- elif isinstance(hess, HessianUpdateStrategy):
286
+ if isinstance(hess, HessianUpdateStrategy):
251
287
  self.H = hess
252
288
  self.H.initialize(self.n, 'hess')
253
289
  self.H_updated = True
254
290
  self.x_prev = None
255
291
  self.g_prev = None
256
- self._nhev = [0]
292
+ _FakeCounter = namedtuple('_FakeCounter', ['ngev', 'nhev'])
293
+ self._wrapped_hess = _FakeCounter(ngev=0, nhev=0)
294
+ else:
295
+ if callable(hess):
296
+ self._wrapped_hess = _ScalarHessWrapper(
297
+ hess,
298
+ x0=x0,
299
+ args=args,
300
+ finite_diff_options=finite_diff_options
301
+ )
302
+ self.H = self._wrapped_hess.H
303
+ self.H_updated = True
304
+ elif hess in FD_METHODS:
305
+ self._wrapped_hess = _ScalarHessWrapper(
306
+ hess,
307
+ x0=x0,
308
+ args=args,
309
+ grad=self._wrapped_grad,
310
+ finite_diff_options=finite_diff_options
311
+ )
312
+ self._update_grad()
313
+ self.H = self._wrapped_hess(self.x, f0=self.g)
314
+ self.H_updated = True
257
315
 
258
316
  @property
259
317
  def nfev(self):
260
- return self._nfev[0]
318
+ return self._nfev + self._wrapped_grad.nfev
261
319
 
262
320
  @property
263
321
  def ngev(self):
264
- return self._ngev[0]
322
+ return self._wrapped_grad.ngev #+ self._wrapped_hess.ngev
265
323
 
266
324
  @property
267
325
  def nhev(self):
268
- return self._nhev[0]
326
+ return self._wrapped_hess.nhev
269
327
 
270
328
  def _update_x(self, x):
271
329
  if isinstance(self._orig_hess, HessianUpdateStrategy):
@@ -293,6 +351,7 @@ class ScalarFunction:
293
351
  def _update_fun(self):
294
352
  if not self.f_updated:
295
353
  fx = self._wrapped_fun(self.x)
354
+ self._nfev += 1
296
355
  if fx < self._lowest_f:
297
356
  self._lowest_x = self.x
298
357
  self._lowest_f = fx
@@ -346,6 +405,114 @@ class ScalarFunction:
346
405
  return self.f, self.g
347
406
 
348
407
 
408
+ class _VectorFunWrapper:
409
+ def __init__(self, fun):
410
+ self.fun = fun
411
+ self.nfev = 0
412
+
413
+ def __call__(self, x):
414
+ self.nfev += 1
415
+ return np.atleast_1d(self.fun(x))
416
+
417
+
418
+ class _VectorJacWrapper:
419
+ """
420
+ Wrapper class for Jacobian calculation
421
+ """
422
+ def __init__(
423
+ self,
424
+ jac,
425
+ fun=None,
426
+ finite_diff_options=None,
427
+ sparse_jacobian=None
428
+ ):
429
+ self.fun = fun
430
+ self.jac = jac
431
+ self.finite_diff_options = finite_diff_options
432
+ self.sparse_jacobian = sparse_jacobian
433
+
434
+ self.njev = 0
435
+ # number of function evaluations consumed by finite difference
436
+ self.nfev = 0
437
+
438
+ def __call__(self, x, f0=None, **kwds):
439
+ # Send a copy because the user may overwrite it.
440
+ # The user of this class might want `x` to remain unchanged.
441
+ if callable(self.jac):
442
+ J = self.jac(x)
443
+ self.njev += 1
444
+ elif self.jac in FD_METHODS:
445
+ J, dct = approx_derivative(
446
+ self.fun,
447
+ x,
448
+ f0=f0,
449
+ **self.finite_diff_options,
450
+ )
451
+ self.nfev += dct['nfev']
452
+
453
+ if self.sparse_jacobian:
454
+ return sps.csr_array(J)
455
+ elif sps.issparse(J):
456
+ return J.toarray()
457
+ elif isinstance(J, LinearOperator):
458
+ return J
459
+ else:
460
+ return np.atleast_2d(J)
461
+
462
+
463
+ class _VectorHessWrapper:
464
+ """
465
+ Wrapper class for Jacobian calculation
466
+ """
467
+ def __init__(
468
+ self,
469
+ hess,
470
+ jac=None,
471
+ finite_diff_options=None,
472
+ ):
473
+ self.jac = jac
474
+ self.hess = hess
475
+ self.finite_diff_options = finite_diff_options
476
+ self.nhev = 0
477
+ # number of jac evaluations consumed by finite difference
478
+ self.njev = 0
479
+
480
+ def __call__(self, x, v, J0=None, **kwds):
481
+ # Send a copy because the user may overwrite it.
482
+ # The user of this class might want `x` to remain unchanged.
483
+ if callable(self.hess):
484
+ self.nhev += 1
485
+ return self._callable_hess(x, v)
486
+ elif self.hess in FD_METHODS:
487
+ return self._fd_hess(x, v, J0=J0)
488
+
489
+ def _fd_hess(self, x, v, J0=None):
490
+ if J0 is None:
491
+ J0 = self.jac(x)
492
+ self.njev += 1
493
+
494
+ # H will be a LinearOperator
495
+ H = approx_derivative(self.jac_dot_v, x,
496
+ f0=J0.T.dot(v),
497
+ args=(v,),
498
+ **self.finite_diff_options)
499
+ return H
500
+
501
+ def jac_dot_v(self, x, v):
502
+ self.njev += 1
503
+ return self.jac(x).T.dot(v)
504
+
505
+ def _callable_hess(self, x, v):
506
+ H = self.hess(x, v)
507
+
508
+ if sps.issparse(H):
509
+ return sps.csr_array(H)
510
+ elif isinstance(H, LinearOperator):
511
+ return H
512
+ else:
513
+ return np.atleast_2d(np.asarray(H))
514
+
515
+
349
516
  class VectorFunction:
350
517
  """Vector function and its derivatives.
351
518
 
@@ -364,8 +531,9 @@ class VectorFunction:
364
531
  of *any* of the methods may overwrite the attribute.
365
532
  """
366
533
  def __init__(self, fun, x0, jac, hess,
367
- finite_diff_rel_step, finite_diff_jac_sparsity,
368
- finite_diff_bounds, sparse_jacobian):
534
+ finite_diff_rel_step=None, finite_diff_jac_sparsity=None,
535
+ finite_diff_bounds=(-np.inf, np.inf), sparse_jacobian=None,
536
+ workers=None):
369
537
  if not callable(jac) and jac not in FD_METHODS:
370
538
  raise ValueError(f"`jac` must be either callable or one of {FD_METHODS}.")
371
539
 
@@ -386,18 +554,26 @@ class VectorFunction:
386
554
  if xp.isdtype(_x.dtype, "real floating"):
387
555
  _dtype = _x.dtype
388
556
 
389
- # promotes to floating
557
+ # store original functions
558
+ self._orig_fun = fun
559
+ self._orig_jac = jac
560
+ self._orig_hess = hess
561
+
562
+ # promotes to floating, ensures that it's a copy
390
563
  self.x = xp.astype(_x, _dtype)
391
564
  self.x_dtype = _dtype
392
565
 
393
566
  self.n = self.x.size
394
- self.nfev = 0
395
- self.njev = 0
396
- self.nhev = 0
567
+ self._nfev = 0
568
+ self._njev = 0
569
+ self._nhev = 0
397
570
  self.f_updated = False
398
571
  self.J_updated = False
399
572
  self.H_updated = False
400
573
 
574
+ # normalize workers
575
+ workers = workers or map
576
+
401
577
  finite_diff_options = {}
402
578
  if jac in FD_METHODS:
403
579
  finite_diff_options["method"] = jac
@@ -407,11 +583,17 @@ class VectorFunction:
407
583
  finite_diff_options["sparsity"] = (finite_diff_jac_sparsity,
408
584
  sparsity_groups)
409
585
  finite_diff_options["bounds"] = finite_diff_bounds
586
+ finite_diff_options["workers"] = workers
587
+ finite_diff_options["full_output"] = True
410
588
  self.x_diff = np.copy(self.x)
411
589
  if hess in FD_METHODS:
412
590
  finite_diff_options["method"] = hess
413
591
  finite_diff_options["rel_step"] = finite_diff_rel_step
414
592
  finite_diff_options["as_linear_operator"] = True
593
+ # workers is not useful for evaluation of the LinearOperator
594
+ # produced by approx_derivative. Only two/three function
595
+ # evaluations are used, and the LinearOperator may persist
596
+ # outside the scope that workers is valid in.
415
597
  self.x_diff = np.copy(self.x)
416
598
  if jac in FD_METHODS and hess in FD_METHODS:
417
599
  raise ValueError("Whenever the Jacobian is estimated via "
@@ -419,122 +601,55 @@ class VectorFunction:
419
601
  "be estimated using one of the quasi-Newton "
420
602
  "strategies.")
421
603
 
422
- # Function evaluation
423
- def fun_wrapped(x):
424
- self.nfev += 1
425
- return np.atleast_1d(fun(x))
426
-
427
- def update_fun():
428
- self.f = fun_wrapped(self.x)
429
-
430
- self._update_fun_impl = update_fun
431
- update_fun()
604
+ self.fun_wrapped = _VectorFunWrapper(fun)
605
+ self._update_fun()
432
606
 
433
607
  self.v = np.zeros_like(self.f)
434
608
  self.m = self.v.size
435
609
 
436
- # Jacobian Evaluation
610
+ # Initial Jacobian Evaluation
437
611
  if callable(jac):
438
- self.J = jac(self.x)
612
+ self.J = jac(xp_copy(self.x))
439
613
  self.J_updated = True
440
- self.njev += 1
441
-
442
- if (sparse_jacobian or
443
- sparse_jacobian is None and sps.issparse(self.J)):
444
- def jac_wrapped(x):
445
- self.njev += 1
446
- return sps.csr_matrix(jac(x))
447
- self.J = sps.csr_matrix(self.J)
448
- self.sparse_jacobian = True
449
-
450
- elif sps.issparse(self.J):
451
- def jac_wrapped(x):
452
- self.njev += 1
453
- return jac(x).toarray()
454
- self.J = self.J.toarray()
455
- self.sparse_jacobian = False
456
-
457
- else:
458
- def jac_wrapped(x):
459
- self.njev += 1
460
- return np.atleast_2d(jac(x))
461
- self.J = np.atleast_2d(self.J)
462
- self.sparse_jacobian = False
463
-
464
- def update_jac():
465
- self.J = jac_wrapped(self.x)
466
-
614
+ self._njev += 1
467
615
  elif jac in FD_METHODS:
468
- self.J = approx_derivative(fun_wrapped, self.x, f0=self.f,
469
- **finite_diff_options)
616
+ self.J, dct = approx_derivative(
617
+ self.fun_wrapped, self.x, f0=self.f, **finite_diff_options
618
+ )
470
619
  self.J_updated = True
620
+ self._nfev += dct['nfev']
621
+
622
+ self.sparse_jacobian = False
623
+ if (sparse_jacobian or
624
+ sparse_jacobian is None and sps.issparse(self.J)):
625
+ # something truthy was specified for sparse_jacobian,
626
+ # or it turns out that the Jacobian was sparse.
627
+ self.J = sps.csr_array(self.J)
628
+ self.sparse_jacobian = True
629
+ elif sps.issparse(self.J):
630
+ self.J = self.J.toarray()
631
+ elif isinstance(self.J, LinearOperator):
632
+ pass
633
+ else:
634
+ self.J = np.atleast_2d(self.J)
471
635
 
472
- if (sparse_jacobian or
473
- sparse_jacobian is None and sps.issparse(self.J)):
474
- def update_jac():
475
- self._update_fun()
476
- self.J = sps.csr_matrix(
477
- approx_derivative(fun_wrapped, self.x, f0=self.f,
478
- **finite_diff_options))
479
- self.J = sps.csr_matrix(self.J)
480
- self.sparse_jacobian = True
481
-
482
- elif sps.issparse(self.J):
483
- def update_jac():
484
- self._update_fun()
485
- self.J = approx_derivative(fun_wrapped, self.x, f0=self.f,
486
- **finite_diff_options).toarray()
487
- self.J = self.J.toarray()
488
- self.sparse_jacobian = False
489
-
490
- else:
491
- def update_jac():
492
- self._update_fun()
493
- self.J = np.atleast_2d(
494
- approx_derivative(fun_wrapped, self.x, f0=self.f,
495
- **finite_diff_options))
496
- self.J = np.atleast_2d(self.J)
497
- self.sparse_jacobian = False
636
+ self.jac_wrapped = _VectorJacWrapper(
637
+ jac,
638
+ fun=self.fun_wrapped,
639
+ finite_diff_options=finite_diff_options,
640
+ sparse_jacobian=self.sparse_jacobian
641
+ )
498
642
 
499
- self._update_jac_impl = update_jac
643
+ self.hess_wrapped = _VectorHessWrapper(
644
+ hess, jac=self.jac_wrapped, finite_diff_options=finite_diff_options
645
+ )
500
646
 
501
647
  # Define Hessian
502
- if callable(hess):
503
- self.H = hess(self.x, self.v)
504
- self.H_updated = True
505
- self.nhev += 1
506
-
507
- if sps.issparse(self.H):
508
- def hess_wrapped(x, v):
509
- self.nhev += 1
510
- return sps.csr_matrix(hess(x, v))
511
- self.H = sps.csr_matrix(self.H)
512
-
513
- elif isinstance(self.H, LinearOperator):
514
- def hess_wrapped(x, v):
515
- self.nhev += 1
516
- return hess(x, v)
517
-
518
- else:
519
- def hess_wrapped(x, v):
520
- self.nhev += 1
521
- return np.atleast_2d(np.asarray(hess(x, v)))
522
- self.H = np.atleast_2d(np.asarray(self.H))
523
-
524
- def update_hess():
525
- self.H = hess_wrapped(self.x, self.v)
526
- elif hess in FD_METHODS:
527
- def jac_dot_v(x, v):
528
- return jac_wrapped(x).T.dot(v)
529
-
530
- def update_hess():
531
- self._update_jac()
532
- self.H = approx_derivative(jac_dot_v, self.x,
533
- f0=self.J.T.dot(self.v),
534
- args=(self.v,),
535
- **finite_diff_options)
536
- update_hess()
648
+ if callable(hess) or hess in FD_METHODS:
649
+ self.H = self.hess_wrapped(xp_copy(self.x), self.v, J0=self.J)
537
650
  self.H_updated = True
651
+ if callable(hess):
652
+ self._nhev += 1
538
653
  elif isinstance(hess, HessianUpdateStrategy):
539
654
  self.H = hess
540
655
  self.H.initialize(self.n, 'hess')
@@ -542,19 +657,26 @@ class VectorFunction:
542
657
  self.x_prev = None
543
658
  self.J_prev = None
544
659
 
545
- def update_hess():
546
- self._update_jac()
547
- # When v is updated before x was updated, then x_prev and
548
- # J_prev are None and we need this check.
549
- if self.x_prev is not None and self.J_prev is not None:
550
- delta_x = self.x - self.x_prev
551
- delta_g = self.J.T.dot(self.v) - self.J_prev.T.dot(self.v)
552
- self.H.update(delta_x, delta_g)
660
+ @property
661
+ def nfev(self):
662
+ return self._nfev + self.jac_wrapped.nfev
553
663
 
554
- self._update_hess_impl = update_hess
664
+ @property
665
+ def njev(self):
666
+ return self._njev + self.hess_wrapped.njev
555
667
 
556
- if isinstance(hess, HessianUpdateStrategy):
557
- def update_x(x):
668
+ @property
669
+ def nhev(self):
670
+ return self._nhev
671
+
672
+ def _update_v(self, v):
673
+ if not np.array_equal(v, self.v):
674
+ self.v = v
675
+ self.H_updated = False
676
+
677
+ def _update_x(self, x):
678
+ if not np.array_equal(x, self.x):
679
+ if isinstance(self._orig_hess, HessianUpdateStrategy):
558
680
  self._update_jac()
559
681
  self.x_prev = self.x
560
682
  self.J_prev = self.J
@@ -564,48 +686,63 @@ class VectorFunction:
564
686
  self.J_updated = False
565
687
  self.H_updated = False
566
688
  self._update_hess()
567
- else:
568
- def update_x(x):
689
+ else:
569
690
  _x = xpx.atleast_nd(self.xp.asarray(x), ndim=1, xp=self.xp)
570
691
  self.x = self.xp.astype(_x, self.x_dtype)
571
692
  self.f_updated = False
572
693
  self.J_updated = False
573
694
  self.H_updated = False
574
695
 
575
- self._update_x_impl = update_x
576
-
577
- def _update_v(self, v):
578
- if not np.array_equal(v, self.v):
579
- self.v = v
580
- self.H_updated = False
581
-
582
- def _update_x(self, x):
583
- if not np.array_equal(x, self.x):
584
- self._update_x_impl(x)
585
-
586
696
  def _update_fun(self):
587
697
  if not self.f_updated:
588
- self._update_fun_impl()
698
+ self.f = self.fun_wrapped(xp_copy(self.x))
699
+ self._nfev += 1
589
700
  self.f_updated = True
590
701
 
591
702
  def _update_jac(self):
592
703
  if not self.J_updated:
593
- self._update_jac_impl()
704
+ if self._orig_jac in FD_METHODS:
705
+ # need to update fun to get f0
706
+ self._update_fun()
707
+ else:
708
+ self._njev += 1
709
+
710
+ self.J = self.jac_wrapped(xp_copy(self.x), f0=self.f)
594
711
  self.J_updated = True
595
712
 
596
713
  def _update_hess(self):
597
714
  if not self.H_updated:
598
- self._update_hess_impl()
715
+ if callable(self._orig_hess):
716
+ self.H = self.hess_wrapped(xp_copy(self.x), self.v)
717
+ self._nhev += 1
718
+ elif self._orig_hess in FD_METHODS:
719
+ self._update_jac()
720
+ self.H = self.hess_wrapped(xp_copy(self.x), self.v, J0=self.J)
721
+ elif isinstance(self._orig_hess, HessianUpdateStrategy):
722
+ self._update_jac()
723
+ # When v is updated before x was updated, then x_prev and
724
+ # J_prev are None and we need this check.
725
+ if self.x_prev is not None and self.J_prev is not None:
726
+ delta_x = self.x - self.x_prev
727
+ delta_g = self.J.T.dot(self.v) - self.J_prev.T.dot(self.v)
728
+ self.H.update(delta_x, delta_g)
729
+
599
730
  self.H_updated = True
600
731
 
601
732
  def fun(self, x):
602
733
  self._update_x(x)
603
734
  self._update_fun()
604
- return self.f
735
+ # returns a copy so that downstream can't overwrite the
736
+ # internal attribute
737
+ return xp_copy(self.f)
605
738
 
606
739
  def jac(self, x):
607
740
  self._update_x(x)
608
741
  self._update_jac()
742
+ if hasattr(self.J, "astype"):
743
+ # returns a copy so that downstream can't overwrite the
744
+ # internal attribute. But one can't copy a LinearOperator
745
+ return self.J.astype(self.J.dtype)
609
746
  return self.J
610
747
 
611
748
  def hess(self, x, v):
@@ -613,6 +750,10 @@ class VectorFunction:
613
750
  self._update_v(v)
614
751
  self._update_x(x)
615
752
  self._update_hess()
753
+ if hasattr(self.H, "astype"):
754
+ # returns a copy so that downstream can't overwrite the
755
+ # internal attribute. But one can't copy non-arrays
756
+ return self.H.astype(self.H.dtype)
616
757
  return self.H
617
758
 
618
759
 
@@ -625,7 +766,7 @@ class LinearVectorFunction:
625
766
  """
626
767
  def __init__(self, A, x0, sparse_jacobian):
627
768
  if sparse_jacobian or sparse_jacobian is None and sps.issparse(A):
628
- self.J = sps.csr_matrix(A)
769
+ self.J = sps.csr_array(A)
629
770
  self.sparse_jacobian = True
630
771
  elif sps.issparse(A):
631
772
  self.J = A.toarray()
@@ -651,7 +792,7 @@ class LinearVectorFunction:
651
792
  self.f_updated = True
652
793
 
653
794
  self.v = np.zeros(self.m, dtype=float)
654
- self.H = sps.csr_matrix((self.n, self.n))
795
+ self.H = sps.csr_array((self.n, self.n))
655
796
 
656
797
  def _update_x(self, x):
657
798
  if not np.array_equal(x, self.x):
@@ -686,7 +827,7 @@ class IdentityVectorFunction(LinearVectorFunction):
686
827
  def __init__(self, x0, sparse_jacobian):
687
828
  n = len(x0)
688
829
  if sparse_jacobian or sparse_jacobian is None:
689
- A = sps.eye(n, format='csr')
830
+ A = sps.eye_array(n, format='csr')
690
831
  sparse_jacobian = True
691
832
  else:
692
833
  A = np.eye(n)