scipy 1.15.3__cp313-cp313t-win_amd64.whl → 1.16.0rc2__cp313-cp313t-win_amd64.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 (759) hide show
  1. scipy/__config__.py +7 -7
  2. scipy/__init__.py +3 -6
  3. scipy/_cyutility.cp313t-win_amd64.dll.a +0 -0
  4. scipy/_cyutility.cp313t-win_amd64.pyd +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.cp313t-win_amd64.dll.a +0 -0
  9. scipy/_lib/_ccallback_c.cp313t-win_amd64.pyd +0 -0
  10. scipy/_lib/_docscrape.py +1 -1
  11. scipy/_lib/_elementwise_iterative_method.py +15 -26
  12. scipy/_lib/_fpumode.cp313t-win_amd64.dll.a +0 -0
  13. scipy/_lib/_fpumode.cp313t-win_amd64.pyd +0 -0
  14. scipy/_lib/_sparse.py +41 -0
  15. scipy/_lib/_test_ccallback.cp313t-win_amd64.dll.a +0 -0
  16. scipy/_lib/_test_ccallback.cp313t-win_amd64.pyd +0 -0
  17. scipy/_lib/_test_deprecation_call.cp313t-win_amd64.dll.a +0 -0
  18. scipy/_lib/_test_deprecation_call.cp313t-win_amd64.pyd +0 -0
  19. scipy/_lib/_test_deprecation_def.cp313t-win_amd64.dll.a +0 -0
  20. scipy/_lib/_test_deprecation_def.cp313t-win_amd64.pyd +0 -0
  21. scipy/_lib/_testutils.py +6 -2
  22. scipy/_lib/_uarray/_uarray.cp313t-win_amd64.dll.a +0 -0
  23. scipy/_lib/_uarray/_uarray.cp313t-win_amd64.pyd +0 -0
  24. scipy/_lib/_util.py +222 -125
  25. scipy/_lib/array_api_compat/__init__.py +4 -4
  26. scipy/_lib/array_api_compat/_internal.py +19 -6
  27. scipy/_lib/array_api_compat/common/__init__.py +1 -1
  28. scipy/_lib/array_api_compat/common/_aliases.py +365 -193
  29. scipy/_lib/array_api_compat/common/_fft.py +94 -64
  30. scipy/_lib/array_api_compat/common/_helpers.py +413 -180
  31. scipy/_lib/array_api_compat/common/_linalg.py +116 -40
  32. scipy/_lib/array_api_compat/common/_typing.py +179 -10
  33. scipy/_lib/array_api_compat/cupy/__init__.py +1 -4
  34. scipy/_lib/array_api_compat/cupy/_aliases.py +61 -41
  35. scipy/_lib/array_api_compat/cupy/_info.py +16 -6
  36. scipy/_lib/array_api_compat/cupy/_typing.py +24 -39
  37. scipy/_lib/array_api_compat/dask/array/__init__.py +6 -3
  38. scipy/_lib/array_api_compat/dask/array/_aliases.py +267 -108
  39. scipy/_lib/array_api_compat/dask/array/_info.py +105 -34
  40. scipy/_lib/array_api_compat/dask/array/fft.py +5 -8
  41. scipy/_lib/array_api_compat/dask/array/linalg.py +21 -22
  42. scipy/_lib/array_api_compat/numpy/__init__.py +13 -15
  43. scipy/_lib/array_api_compat/numpy/_aliases.py +98 -49
  44. scipy/_lib/array_api_compat/numpy/_info.py +36 -16
  45. scipy/_lib/array_api_compat/numpy/_typing.py +27 -43
  46. scipy/_lib/array_api_compat/numpy/fft.py +11 -5
  47. scipy/_lib/array_api_compat/numpy/linalg.py +75 -22
  48. scipy/_lib/array_api_compat/torch/__init__.py +3 -5
  49. scipy/_lib/array_api_compat/torch/_aliases.py +262 -159
  50. scipy/_lib/array_api_compat/torch/_info.py +27 -16
  51. scipy/_lib/array_api_compat/torch/_typing.py +3 -0
  52. scipy/_lib/array_api_compat/torch/fft.py +17 -18
  53. scipy/_lib/array_api_compat/torch/linalg.py +16 -16
  54. scipy/_lib/array_api_extra/__init__.py +26 -3
  55. scipy/_lib/array_api_extra/_delegation.py +171 -0
  56. scipy/_lib/array_api_extra/_lib/__init__.py +1 -0
  57. scipy/_lib/array_api_extra/_lib/_at.py +463 -0
  58. scipy/_lib/array_api_extra/_lib/_backends.py +46 -0
  59. scipy/_lib/array_api_extra/_lib/_funcs.py +937 -0
  60. scipy/_lib/array_api_extra/_lib/_lazy.py +357 -0
  61. scipy/_lib/array_api_extra/_lib/_testing.py +278 -0
  62. scipy/_lib/array_api_extra/_lib/_utils/__init__.py +1 -0
  63. scipy/_lib/array_api_extra/_lib/_utils/_compat.py +74 -0
  64. scipy/_lib/array_api_extra/_lib/_utils/_compat.pyi +45 -0
  65. scipy/_lib/array_api_extra/_lib/_utils/_helpers.py +559 -0
  66. scipy/_lib/array_api_extra/_lib/_utils/_typing.py +10 -0
  67. scipy/_lib/array_api_extra/_lib/_utils/_typing.pyi +105 -0
  68. scipy/_lib/array_api_extra/testing.py +359 -0
  69. scipy/_lib/decorator.py +2 -2
  70. scipy/_lib/doccer.py +1 -7
  71. scipy/_lib/messagestream.cp313t-win_amd64.dll.a +0 -0
  72. scipy/_lib/messagestream.cp313t-win_amd64.pyd +0 -0
  73. scipy/_lib/pyprima/__init__.py +212 -0
  74. scipy/_lib/pyprima/cobyla/__init__.py +0 -0
  75. scipy/_lib/pyprima/cobyla/cobyla.py +559 -0
  76. scipy/_lib/pyprima/cobyla/cobylb.py +714 -0
  77. scipy/_lib/pyprima/cobyla/geometry.py +226 -0
  78. scipy/_lib/pyprima/cobyla/initialize.py +215 -0
  79. scipy/_lib/pyprima/cobyla/trustregion.py +492 -0
  80. scipy/_lib/pyprima/cobyla/update.py +289 -0
  81. scipy/_lib/pyprima/common/__init__.py +0 -0
  82. scipy/_lib/pyprima/common/_bounds.py +34 -0
  83. scipy/_lib/pyprima/common/_linear_constraints.py +46 -0
  84. scipy/_lib/pyprima/common/_nonlinear_constraints.py +54 -0
  85. scipy/_lib/pyprima/common/_project.py +173 -0
  86. scipy/_lib/pyprima/common/checkbreak.py +93 -0
  87. scipy/_lib/pyprima/common/consts.py +47 -0
  88. scipy/_lib/pyprima/common/evaluate.py +99 -0
  89. scipy/_lib/pyprima/common/history.py +38 -0
  90. scipy/_lib/pyprima/common/infos.py +30 -0
  91. scipy/_lib/pyprima/common/linalg.py +435 -0
  92. scipy/_lib/pyprima/common/message.py +290 -0
  93. scipy/_lib/pyprima/common/powalg.py +131 -0
  94. scipy/_lib/pyprima/common/preproc.py +277 -0
  95. scipy/_lib/pyprima/common/present.py +5 -0
  96. scipy/_lib/pyprima/common/ratio.py +54 -0
  97. scipy/_lib/pyprima/common/redrho.py +47 -0
  98. scipy/_lib/pyprima/common/selectx.py +296 -0
  99. scipy/_lib/tests/test__util.py +105 -121
  100. scipy/_lib/tests/test_array_api.py +166 -35
  101. scipy/_lib/tests/test_bunch.py +7 -0
  102. scipy/_lib/tests/test_ccallback.py +2 -10
  103. scipy/_lib/tests/test_public_api.py +13 -0
  104. scipy/cluster/_hierarchy.cp313t-win_amd64.dll.a +0 -0
  105. scipy/cluster/_hierarchy.cp313t-win_amd64.pyd +0 -0
  106. scipy/cluster/_optimal_leaf_ordering.cp313t-win_amd64.dll.a +0 -0
  107. scipy/cluster/_optimal_leaf_ordering.cp313t-win_amd64.pyd +0 -0
  108. scipy/cluster/_vq.cp313t-win_amd64.dll.a +0 -0
  109. scipy/cluster/_vq.cp313t-win_amd64.pyd +0 -0
  110. scipy/cluster/hierarchy.py +393 -223
  111. scipy/cluster/tests/test_hierarchy.py +273 -335
  112. scipy/cluster/tests/test_vq.py +45 -61
  113. scipy/cluster/vq.py +39 -35
  114. scipy/conftest.py +263 -157
  115. scipy/constants/_constants.py +4 -1
  116. scipy/constants/tests/test_codata.py +2 -2
  117. scipy/constants/tests/test_constants.py +11 -18
  118. scipy/datasets/_download_all.py +15 -1
  119. scipy/datasets/_fetchers.py +7 -1
  120. scipy/datasets/_utils.py +1 -1
  121. scipy/differentiate/_differentiate.py +25 -25
  122. scipy/differentiate/tests/test_differentiate.py +24 -25
  123. scipy/fft/_basic.py +20 -0
  124. scipy/fft/_helper.py +3 -34
  125. scipy/fft/_pocketfft/helper.py +29 -1
  126. scipy/fft/_pocketfft/pypocketfft.cp313t-win_amd64.dll.a +0 -0
  127. scipy/fft/_pocketfft/pypocketfft.cp313t-win_amd64.pyd +0 -0
  128. scipy/fft/_pocketfft/tests/test_basic.py +2 -4
  129. scipy/fft/_pocketfft/tests/test_real_transforms.py +4 -4
  130. scipy/fft/_realtransforms.py +13 -0
  131. scipy/fft/tests/test_basic.py +27 -25
  132. scipy/fft/tests/test_fftlog.py +16 -7
  133. scipy/fft/tests/test_helper.py +18 -34
  134. scipy/fft/tests/test_real_transforms.py +8 -10
  135. scipy/fftpack/convolve.cp313t-win_amd64.dll.a +0 -0
  136. scipy/fftpack/convolve.cp313t-win_amd64.pyd +0 -0
  137. scipy/fftpack/tests/test_basic.py +2 -4
  138. scipy/fftpack/tests/test_real_transforms.py +8 -9
  139. scipy/integrate/_bvp.py +9 -3
  140. scipy/integrate/_cubature.py +3 -2
  141. scipy/integrate/_dop.cp313t-win_amd64.dll.a +0 -0
  142. scipy/integrate/_dop.cp313t-win_amd64.pyd +0 -0
  143. scipy/integrate/_lsoda.cp313t-win_amd64.dll.a +0 -0
  144. scipy/integrate/_lsoda.cp313t-win_amd64.pyd +0 -0
  145. scipy/integrate/_ode.py +9 -2
  146. scipy/integrate/_odepack.cp313t-win_amd64.dll.a +0 -0
  147. scipy/integrate/_odepack.cp313t-win_amd64.pyd +0 -0
  148. scipy/integrate/_quad_vec.py +21 -29
  149. scipy/integrate/_quadpack.cp313t-win_amd64.dll.a +0 -0
  150. scipy/integrate/_quadpack.cp313t-win_amd64.pyd +0 -0
  151. scipy/integrate/_quadpack_py.py +11 -7
  152. scipy/integrate/_quadrature.py +3 -3
  153. scipy/integrate/_rules/_base.py +2 -2
  154. scipy/integrate/_tanhsinh.py +48 -47
  155. scipy/integrate/_test_multivariate.cp313t-win_amd64.dll.a +0 -0
  156. scipy/integrate/_test_multivariate.cp313t-win_amd64.pyd +0 -0
  157. scipy/integrate/_test_odeint_banded.cp313t-win_amd64.dll.a +0 -0
  158. scipy/integrate/_test_odeint_banded.cp313t-win_amd64.pyd +0 -0
  159. scipy/integrate/_vode.cp313t-win_amd64.dll.a +0 -0
  160. scipy/integrate/_vode.cp313t-win_amd64.pyd +0 -0
  161. scipy/integrate/tests/test__quad_vec.py +0 -6
  162. scipy/integrate/tests/test_banded_ode_solvers.py +85 -0
  163. scipy/integrate/tests/test_cubature.py +21 -35
  164. scipy/integrate/tests/test_quadrature.py +6 -8
  165. scipy/integrate/tests/test_tanhsinh.py +56 -48
  166. scipy/interpolate/__init__.py +70 -58
  167. scipy/interpolate/_bary_rational.py +22 -22
  168. scipy/interpolate/_bsplines.py +119 -66
  169. scipy/interpolate/_cubic.py +65 -50
  170. scipy/interpolate/_dfitpack.cp313t-win_amd64.dll.a +0 -0
  171. scipy/interpolate/_dfitpack.cp313t-win_amd64.pyd +0 -0
  172. scipy/interpolate/_dierckx.cp313t-win_amd64.dll.a +0 -0
  173. scipy/interpolate/_dierckx.cp313t-win_amd64.pyd +0 -0
  174. scipy/interpolate/_fitpack.cp313t-win_amd64.dll.a +0 -0
  175. scipy/interpolate/_fitpack.cp313t-win_amd64.pyd +0 -0
  176. scipy/interpolate/_fitpack2.py +9 -6
  177. scipy/interpolate/_fitpack_impl.py +32 -26
  178. scipy/interpolate/_fitpack_repro.py +23 -19
  179. scipy/interpolate/_interpnd.cp313t-win_amd64.dll.a +0 -0
  180. scipy/interpolate/_interpnd.cp313t-win_amd64.pyd +0 -0
  181. scipy/interpolate/_interpolate.py +30 -12
  182. scipy/interpolate/_ndbspline.py +13 -18
  183. scipy/interpolate/_ndgriddata.py +5 -8
  184. scipy/interpolate/_polyint.py +95 -31
  185. scipy/interpolate/_ppoly.cp313t-win_amd64.dll.a +0 -0
  186. scipy/interpolate/_ppoly.cp313t-win_amd64.pyd +0 -0
  187. scipy/interpolate/_rbf.py +2 -2
  188. scipy/interpolate/_rbfinterp.py +1 -1
  189. scipy/interpolate/_rbfinterp_pythran.cp313t-win_amd64.dll.a +0 -0
  190. scipy/interpolate/_rbfinterp_pythran.cp313t-win_amd64.pyd +0 -0
  191. scipy/interpolate/_rgi.py +31 -26
  192. scipy/interpolate/_rgi_cython.cp313t-win_amd64.dll.a +0 -0
  193. scipy/interpolate/_rgi_cython.cp313t-win_amd64.pyd +0 -0
  194. scipy/interpolate/dfitpack.py +0 -20
  195. scipy/interpolate/interpnd.py +1 -2
  196. scipy/interpolate/tests/test_bary_rational.py +2 -2
  197. scipy/interpolate/tests/test_bsplines.py +97 -1
  198. scipy/interpolate/tests/test_fitpack2.py +39 -1
  199. scipy/interpolate/tests/test_interpnd.py +32 -20
  200. scipy/interpolate/tests/test_interpolate.py +48 -4
  201. scipy/interpolate/tests/test_rgi.py +2 -1
  202. scipy/io/_fast_matrix_market/__init__.py +2 -0
  203. scipy/io/_fast_matrix_market/_fmm_core.cp313t-win_amd64.dll.a +0 -0
  204. scipy/io/_fast_matrix_market/_fmm_core.cp313t-win_amd64.pyd +0 -0
  205. scipy/io/_harwell_boeing/_fortran_format_parser.py +19 -16
  206. scipy/io/_harwell_boeing/hb.py +7 -11
  207. scipy/io/_idl.py +5 -7
  208. scipy/io/_netcdf.py +15 -5
  209. scipy/io/_test_fortran.cp313t-win_amd64.dll.a +0 -0
  210. scipy/io/_test_fortran.cp313t-win_amd64.pyd +0 -0
  211. scipy/io/arff/tests/test_arffread.py +3 -3
  212. scipy/io/matlab/__init__.py +5 -3
  213. scipy/io/matlab/_mio.py +4 -1
  214. scipy/io/matlab/_mio5.py +19 -13
  215. scipy/io/matlab/_mio5_utils.cp313t-win_amd64.dll.a +0 -0
  216. scipy/io/matlab/_mio5_utils.cp313t-win_amd64.pyd +0 -0
  217. scipy/io/matlab/_mio_utils.cp313t-win_amd64.dll.a +0 -0
  218. scipy/io/matlab/_mio_utils.cp313t-win_amd64.pyd +0 -0
  219. scipy/io/matlab/_miobase.py +4 -1
  220. scipy/io/matlab/_streams.cp313t-win_amd64.dll.a +0 -0
  221. scipy/io/matlab/_streams.cp313t-win_amd64.pyd +0 -0
  222. scipy/io/matlab/tests/test_mio.py +46 -18
  223. scipy/io/matlab/tests/test_mio_funcs.py +1 -1
  224. scipy/io/tests/test_mmio.py +7 -1
  225. scipy/io/tests/test_wavfile.py +41 -0
  226. scipy/io/wavfile.py +57 -10
  227. scipy/linalg/_basic.py +113 -86
  228. scipy/linalg/_cythonized_array_utils.cp313t-win_amd64.dll.a +0 -0
  229. scipy/linalg/_cythonized_array_utils.cp313t-win_amd64.pyd +0 -0
  230. scipy/linalg/_decomp.py +22 -9
  231. scipy/linalg/_decomp_cholesky.py +28 -13
  232. scipy/linalg/_decomp_cossin.py +45 -30
  233. scipy/linalg/_decomp_interpolative.cp313t-win_amd64.dll.a +0 -0
  234. scipy/linalg/_decomp_interpolative.cp313t-win_amd64.pyd +0 -0
  235. scipy/linalg/_decomp_ldl.py +4 -1
  236. scipy/linalg/_decomp_lu.py +18 -6
  237. scipy/linalg/_decomp_lu_cython.cp313t-win_amd64.dll.a +0 -0
  238. scipy/linalg/_decomp_lu_cython.cp313t-win_amd64.pyd +0 -0
  239. scipy/linalg/_decomp_polar.py +2 -0
  240. scipy/linalg/_decomp_qr.py +6 -2
  241. scipy/linalg/_decomp_qz.py +3 -0
  242. scipy/linalg/_decomp_schur.py +3 -1
  243. scipy/linalg/_decomp_svd.py +13 -2
  244. scipy/linalg/_decomp_update.cp313t-win_amd64.dll.a +0 -0
  245. scipy/linalg/_decomp_update.cp313t-win_amd64.pyd +0 -0
  246. scipy/linalg/_expm_frechet.py +4 -0
  247. scipy/linalg/_fblas.cp313t-win_amd64.dll.a +0 -0
  248. scipy/linalg/_fblas.cp313t-win_amd64.pyd +0 -0
  249. scipy/linalg/_flapack.cp313t-win_amd64.dll.a +0 -0
  250. scipy/linalg/_flapack.cp313t-win_amd64.pyd +0 -0
  251. scipy/linalg/_linalg_pythran.cp313t-win_amd64.dll.a +0 -0
  252. scipy/linalg/_linalg_pythran.cp313t-win_amd64.pyd +0 -0
  253. scipy/linalg/_matfuncs.py +187 -4
  254. scipy/linalg/_matfuncs_expm.cp313t-win_amd64.dll.a +0 -0
  255. scipy/linalg/_matfuncs_expm.cp313t-win_amd64.pyd +0 -0
  256. scipy/linalg/_matfuncs_schur_sqrtm.cp313t-win_amd64.dll.a +0 -0
  257. scipy/linalg/_matfuncs_schur_sqrtm.cp313t-win_amd64.pyd +0 -0
  258. scipy/linalg/_matfuncs_sqrtm.py +1 -99
  259. scipy/linalg/_matfuncs_sqrtm_triu.cp313t-win_amd64.dll.a +0 -0
  260. scipy/linalg/_matfuncs_sqrtm_triu.cp313t-win_amd64.pyd +0 -0
  261. scipy/linalg/_procrustes.py +2 -0
  262. scipy/linalg/_sketches.py +17 -6
  263. scipy/linalg/_solve_toeplitz.cp313t-win_amd64.dll.a +0 -0
  264. scipy/linalg/_solve_toeplitz.cp313t-win_amd64.pyd +0 -0
  265. scipy/linalg/_solvers.py +7 -2
  266. scipy/linalg/_special_matrices.py +26 -36
  267. scipy/linalg/cython_blas.cp313t-win_amd64.dll.a +0 -0
  268. scipy/linalg/cython_blas.cp313t-win_amd64.pyd +0 -0
  269. scipy/linalg/cython_lapack.cp313t-win_amd64.dll.a +0 -0
  270. scipy/linalg/cython_lapack.cp313t-win_amd64.pyd +0 -0
  271. scipy/linalg/lapack.py +22 -2
  272. scipy/linalg/tests/_cython_examples/meson.build +7 -0
  273. scipy/linalg/tests/test_basic.py +31 -16
  274. scipy/linalg/tests/test_batch.py +588 -0
  275. scipy/linalg/tests/test_cythonized_array_utils.py +0 -2
  276. scipy/linalg/tests/test_decomp.py +40 -3
  277. scipy/linalg/tests/test_decomp_cossin.py +14 -0
  278. scipy/linalg/tests/test_decomp_ldl.py +1 -1
  279. scipy/linalg/tests/test_lapack.py +115 -7
  280. scipy/linalg/tests/test_matfuncs.py +157 -102
  281. scipy/linalg/tests/test_procrustes.py +0 -7
  282. scipy/linalg/tests/test_solve_toeplitz.py +1 -1
  283. scipy/linalg/tests/test_special_matrices.py +1 -5
  284. scipy/ndimage/__init__.py +1 -0
  285. scipy/ndimage/_ctest.cp313t-win_amd64.dll.a +0 -0
  286. scipy/ndimage/_ctest.cp313t-win_amd64.pyd +0 -0
  287. scipy/ndimage/_cytest.cp313t-win_amd64.dll.a +0 -0
  288. scipy/ndimage/_cytest.cp313t-win_amd64.pyd +0 -0
  289. scipy/ndimage/_delegators.py +8 -2
  290. scipy/ndimage/_filters.py +453 -5
  291. scipy/ndimage/_interpolation.py +36 -6
  292. scipy/ndimage/_measurements.py +4 -2
  293. scipy/ndimage/_morphology.py +5 -0
  294. scipy/ndimage/_nd_image.cp313t-win_amd64.dll.a +0 -0
  295. scipy/ndimage/_nd_image.cp313t-win_amd64.pyd +0 -0
  296. scipy/ndimage/_ni_docstrings.py +5 -1
  297. scipy/ndimage/_ni_label.cp313t-win_amd64.dll.a +0 -0
  298. scipy/ndimage/_ni_label.cp313t-win_amd64.pyd +0 -0
  299. scipy/ndimage/_ni_support.py +1 -5
  300. scipy/ndimage/_rank_filter_1d.cp313t-win_amd64.dll.a +0 -0
  301. scipy/ndimage/_rank_filter_1d.cp313t-win_amd64.pyd +0 -0
  302. scipy/ndimage/_support_alternative_backends.py +18 -6
  303. scipy/ndimage/tests/test_filters.py +370 -259
  304. scipy/ndimage/tests/test_fourier.py +7 -9
  305. scipy/ndimage/tests/test_interpolation.py +68 -61
  306. scipy/ndimage/tests/test_measurements.py +18 -35
  307. scipy/ndimage/tests/test_morphology.py +143 -131
  308. scipy/ndimage/tests/test_splines.py +1 -3
  309. scipy/odr/__odrpack.cp313t-win_amd64.dll.a +0 -0
  310. scipy/odr/__odrpack.cp313t-win_amd64.pyd +0 -0
  311. scipy/optimize/_basinhopping.py +13 -7
  312. scipy/optimize/_bglu_dense.cp313t-win_amd64.dll.a +0 -0
  313. scipy/optimize/_bglu_dense.cp313t-win_amd64.pyd +0 -0
  314. scipy/optimize/_bracket.py +17 -24
  315. scipy/optimize/_chandrupatla.py +9 -10
  316. scipy/optimize/_cobyla_py.py +104 -123
  317. scipy/optimize/_constraints.py +14 -10
  318. scipy/optimize/_differentiable_functions.py +371 -230
  319. scipy/optimize/_differentialevolution.py +4 -3
  320. scipy/optimize/_direct.cp313t-win_amd64.dll.a +0 -0
  321. scipy/optimize/_direct.cp313t-win_amd64.pyd +0 -0
  322. scipy/optimize/_dual_annealing.py +1 -1
  323. scipy/optimize/_elementwise.py +1 -4
  324. scipy/optimize/_group_columns.cp313t-win_amd64.dll.a +0 -0
  325. scipy/optimize/_group_columns.cp313t-win_amd64.pyd +0 -0
  326. scipy/optimize/_highspy/_core.cp313t-win_amd64.dll.a +0 -0
  327. scipy/optimize/_highspy/_core.cp313t-win_amd64.pyd +0 -0
  328. scipy/optimize/_highspy/_highs_options.cp313t-win_amd64.dll.a +0 -0
  329. scipy/optimize/_highspy/_highs_options.cp313t-win_amd64.pyd +0 -0
  330. scipy/optimize/_lbfgsb.cp313t-win_amd64.dll.a +0 -0
  331. scipy/optimize/_lbfgsb.cp313t-win_amd64.pyd +0 -0
  332. scipy/optimize/_lbfgsb_py.py +57 -16
  333. scipy/optimize/_linprog_doc.py +2 -2
  334. scipy/optimize/_linprog_highs.py +2 -2
  335. scipy/optimize/_linprog_ip.py +25 -10
  336. scipy/optimize/_linprog_util.py +14 -16
  337. scipy/optimize/_lsap.cp313t-win_amd64.dll.a +0 -0
  338. scipy/optimize/_lsap.cp313t-win_amd64.pyd +0 -0
  339. scipy/optimize/_lsq/common.py +3 -3
  340. scipy/optimize/_lsq/dogbox.py +16 -2
  341. scipy/optimize/_lsq/givens_elimination.cp313t-win_amd64.dll.a +0 -0
  342. scipy/optimize/_lsq/givens_elimination.cp313t-win_amd64.pyd +0 -0
  343. scipy/optimize/_lsq/least_squares.py +198 -126
  344. scipy/optimize/_lsq/lsq_linear.py +6 -6
  345. scipy/optimize/_lsq/trf.py +35 -8
  346. scipy/optimize/_milp.py +3 -1
  347. scipy/optimize/_minimize.py +105 -36
  348. scipy/optimize/_minpack.cp313t-win_amd64.dll.a +0 -0
  349. scipy/optimize/_minpack.cp313t-win_amd64.pyd +0 -0
  350. scipy/optimize/_minpack_py.py +21 -14
  351. scipy/optimize/_moduleTNC.cp313t-win_amd64.dll.a +0 -0
  352. scipy/optimize/_moduleTNC.cp313t-win_amd64.pyd +0 -0
  353. scipy/optimize/_nnls.py +20 -21
  354. scipy/optimize/_nonlin.py +34 -3
  355. scipy/optimize/_numdiff.py +288 -110
  356. scipy/optimize/_optimize.py +86 -48
  357. scipy/optimize/_pava_pybind.cp313t-win_amd64.dll.a +0 -0
  358. scipy/optimize/_pava_pybind.cp313t-win_amd64.pyd +0 -0
  359. scipy/optimize/_remove_redundancy.py +5 -5
  360. scipy/optimize/_root_scalar.py +1 -1
  361. scipy/optimize/_shgo.py +6 -0
  362. scipy/optimize/_shgo_lib/_complex.py +1 -1
  363. scipy/optimize/_slsqp_py.py +216 -124
  364. scipy/optimize/_slsqplib.cp313t-win_amd64.dll.a +0 -0
  365. scipy/optimize/_slsqplib.cp313t-win_amd64.pyd +0 -0
  366. scipy/optimize/_spectral.py +1 -1
  367. scipy/optimize/_tnc.py +8 -1
  368. scipy/optimize/_trlib/_trlib.cp313t-win_amd64.dll.a +0 -0
  369. scipy/optimize/_trlib/_trlib.cp313t-win_amd64.pyd +0 -0
  370. scipy/optimize/_trustregion.py +20 -6
  371. scipy/optimize/_trustregion_constr/canonical_constraint.py +7 -7
  372. scipy/optimize/_trustregion_constr/equality_constrained_sqp.py +1 -1
  373. scipy/optimize/_trustregion_constr/minimize_trustregion_constr.py +11 -3
  374. scipy/optimize/_trustregion_constr/projections.py +12 -8
  375. scipy/optimize/_trustregion_constr/qp_subproblem.py +9 -9
  376. scipy/optimize/_trustregion_constr/tests/test_projections.py +7 -7
  377. scipy/optimize/_trustregion_constr/tests/test_qp_subproblem.py +77 -77
  378. scipy/optimize/_trustregion_constr/tr_interior_point.py +5 -5
  379. scipy/optimize/_trustregion_exact.py +0 -1
  380. scipy/optimize/_zeros.cp313t-win_amd64.dll.a +0 -0
  381. scipy/optimize/_zeros.cp313t-win_amd64.pyd +0 -0
  382. scipy/optimize/_zeros_py.py +97 -17
  383. scipy/optimize/cython_optimize/_zeros.cp313t-win_amd64.dll.a +0 -0
  384. scipy/optimize/cython_optimize/_zeros.cp313t-win_amd64.pyd +0 -0
  385. scipy/optimize/slsqp.py +0 -1
  386. scipy/optimize/tests/test__basinhopping.py +1 -1
  387. scipy/optimize/tests/test__differential_evolution.py +4 -4
  388. scipy/optimize/tests/test__linprog_clean_inputs.py +5 -3
  389. scipy/optimize/tests/test__numdiff.py +66 -22
  390. scipy/optimize/tests/test__remove_redundancy.py +2 -2
  391. scipy/optimize/tests/test__shgo.py +9 -1
  392. scipy/optimize/tests/test_bracket.py +36 -46
  393. scipy/optimize/tests/test_chandrupatla.py +133 -135
  394. scipy/optimize/tests/test_cobyla.py +74 -45
  395. scipy/optimize/tests/test_constraints.py +1 -1
  396. scipy/optimize/tests/test_differentiable_functions.py +226 -6
  397. scipy/optimize/tests/test_lbfgsb_hessinv.py +22 -0
  398. scipy/optimize/tests/test_least_squares.py +125 -13
  399. scipy/optimize/tests/test_linear_assignment.py +3 -3
  400. scipy/optimize/tests/test_linprog.py +3 -3
  401. scipy/optimize/tests/test_lsq_linear.py +6 -6
  402. scipy/optimize/tests/test_minimize_constrained.py +2 -2
  403. scipy/optimize/tests/test_minpack.py +4 -4
  404. scipy/optimize/tests/test_nnls.py +43 -3
  405. scipy/optimize/tests/test_nonlin.py +36 -0
  406. scipy/optimize/tests/test_optimize.py +95 -17
  407. scipy/optimize/tests/test_slsqp.py +36 -4
  408. scipy/optimize/tests/test_zeros.py +34 -1
  409. scipy/signal/__init__.py +12 -23
  410. scipy/signal/_delegators.py +568 -0
  411. scipy/signal/_filter_design.py +459 -241
  412. scipy/signal/_fir_filter_design.py +262 -90
  413. scipy/signal/_lti_conversion.py +3 -2
  414. scipy/signal/_ltisys.py +118 -91
  415. scipy/signal/_max_len_seq_inner.cp313t-win_amd64.dll.a +0 -0
  416. scipy/signal/_max_len_seq_inner.cp313t-win_amd64.pyd +0 -0
  417. scipy/signal/_peak_finding_utils.cp313t-win_amd64.dll.a +0 -0
  418. scipy/signal/_peak_finding_utils.cp313t-win_amd64.pyd +0 -0
  419. scipy/signal/_polyutils.py +172 -0
  420. scipy/signal/_short_time_fft.py +519 -70
  421. scipy/signal/_signal_api.py +30 -0
  422. scipy/signal/_signaltools.py +719 -399
  423. scipy/signal/_sigtools.cp313t-win_amd64.dll.a +0 -0
  424. scipy/signal/_sigtools.cp313t-win_amd64.pyd +0 -0
  425. scipy/signal/_sosfilt.cp313t-win_amd64.dll.a +0 -0
  426. scipy/signal/_sosfilt.cp313t-win_amd64.pyd +0 -0
  427. scipy/signal/_spectral_py.py +230 -50
  428. scipy/signal/_spline.cp313t-win_amd64.dll.a +0 -0
  429. scipy/signal/_spline.cp313t-win_amd64.pyd +0 -0
  430. scipy/signal/_spline_filters.py +108 -68
  431. scipy/signal/_support_alternative_backends.py +73 -0
  432. scipy/signal/_upfirdn.py +4 -1
  433. scipy/signal/_upfirdn_apply.cp313t-win_amd64.dll.a +0 -0
  434. scipy/signal/_upfirdn_apply.cp313t-win_amd64.pyd +0 -0
  435. scipy/signal/_waveforms.py +2 -11
  436. scipy/signal/_wavelets.py +1 -1
  437. scipy/signal/fir_filter_design.py +1 -0
  438. scipy/signal/spline.py +4 -11
  439. scipy/signal/tests/_scipy_spectral_test_shim.py +2 -171
  440. scipy/signal/tests/test_bsplines.py +114 -79
  441. scipy/signal/tests/test_cont2discrete.py +9 -2
  442. scipy/signal/tests/test_filter_design.py +721 -481
  443. scipy/signal/tests/test_fir_filter_design.py +332 -140
  444. scipy/signal/tests/test_savitzky_golay.py +4 -3
  445. scipy/signal/tests/test_short_time_fft.py +221 -3
  446. scipy/signal/tests/test_signaltools.py +2144 -1348
  447. scipy/signal/tests/test_spectral.py +50 -6
  448. scipy/signal/tests/test_splines.py +161 -96
  449. scipy/signal/tests/test_upfirdn.py +84 -50
  450. scipy/signal/tests/test_waveforms.py +20 -0
  451. scipy/signal/tests/test_windows.py +607 -466
  452. scipy/signal/windows/_windows.py +287 -148
  453. scipy/sparse/__init__.py +23 -4
  454. scipy/sparse/_base.py +270 -108
  455. scipy/sparse/_bsr.py +7 -4
  456. scipy/sparse/_compressed.py +59 -231
  457. scipy/sparse/_construct.py +90 -38
  458. scipy/sparse/_coo.py +115 -181
  459. scipy/sparse/_csc.py +4 -4
  460. scipy/sparse/_csparsetools.cp313t-win_amd64.dll.a +0 -0
  461. scipy/sparse/_csparsetools.cp313t-win_amd64.pyd +0 -0
  462. scipy/sparse/_csr.py +2 -2
  463. scipy/sparse/_data.py +48 -48
  464. scipy/sparse/_dia.py +105 -18
  465. scipy/sparse/_dok.py +0 -23
  466. scipy/sparse/_index.py +4 -4
  467. scipy/sparse/_matrix.py +23 -0
  468. scipy/sparse/_sparsetools.cp313t-win_amd64.dll.a +0 -0
  469. scipy/sparse/_sparsetools.cp313t-win_amd64.pyd +0 -0
  470. scipy/sparse/_sputils.py +37 -22
  471. scipy/sparse/base.py +0 -9
  472. scipy/sparse/bsr.py +0 -14
  473. scipy/sparse/compressed.py +0 -23
  474. scipy/sparse/construct.py +0 -6
  475. scipy/sparse/coo.py +0 -14
  476. scipy/sparse/csc.py +0 -3
  477. scipy/sparse/csgraph/_flow.cp313t-win_amd64.dll.a +0 -0
  478. scipy/sparse/csgraph/_flow.cp313t-win_amd64.pyd +0 -0
  479. scipy/sparse/csgraph/_matching.cp313t-win_amd64.dll.a +0 -0
  480. scipy/sparse/csgraph/_matching.cp313t-win_amd64.pyd +0 -0
  481. scipy/sparse/csgraph/_min_spanning_tree.cp313t-win_amd64.dll.a +0 -0
  482. scipy/sparse/csgraph/_min_spanning_tree.cp313t-win_amd64.pyd +0 -0
  483. scipy/sparse/csgraph/_reordering.cp313t-win_amd64.dll.a +0 -0
  484. scipy/sparse/csgraph/_reordering.cp313t-win_amd64.pyd +0 -0
  485. scipy/sparse/csgraph/_shortest_path.cp313t-win_amd64.dll.a +0 -0
  486. scipy/sparse/csgraph/_shortest_path.cp313t-win_amd64.pyd +0 -0
  487. scipy/sparse/csgraph/_tools.cp313t-win_amd64.dll.a +0 -0
  488. scipy/sparse/csgraph/_tools.cp313t-win_amd64.pyd +0 -0
  489. scipy/sparse/csgraph/_traversal.cp313t-win_amd64.dll.a +0 -0
  490. scipy/sparse/csgraph/_traversal.cp313t-win_amd64.pyd +0 -0
  491. scipy/sparse/csgraph/tests/test_matching.py +14 -2
  492. scipy/sparse/csgraph/tests/test_pydata_sparse.py +4 -1
  493. scipy/sparse/csgraph/tests/test_shortest_path.py +83 -27
  494. scipy/sparse/csr.py +0 -5
  495. scipy/sparse/data.py +1 -6
  496. scipy/sparse/dia.py +0 -7
  497. scipy/sparse/dok.py +0 -10
  498. scipy/sparse/linalg/_dsolve/_superlu.cp313t-win_amd64.dll.a +0 -0
  499. scipy/sparse/linalg/_dsolve/_superlu.cp313t-win_amd64.pyd +0 -0
  500. scipy/sparse/linalg/_dsolve/linsolve.py +9 -0
  501. scipy/sparse/linalg/_dsolve/tests/test_linsolve.py +35 -28
  502. scipy/sparse/linalg/_eigen/arpack/_arpack.cp313t-win_amd64.dll.a +0 -0
  503. scipy/sparse/linalg/_eigen/arpack/_arpack.cp313t-win_amd64.pyd +0 -0
  504. scipy/sparse/linalg/_eigen/arpack/arpack.py +23 -17
  505. scipy/sparse/linalg/_eigen/lobpcg/lobpcg.py +6 -6
  506. scipy/sparse/linalg/_interface.py +17 -18
  507. scipy/sparse/linalg/_isolve/_gcrotmk.py +4 -4
  508. scipy/sparse/linalg/_isolve/iterative.py +51 -45
  509. scipy/sparse/linalg/_isolve/lgmres.py +6 -6
  510. scipy/sparse/linalg/_isolve/minres.py +5 -5
  511. scipy/sparse/linalg/_isolve/tfqmr.py +7 -7
  512. scipy/sparse/linalg/_isolve/utils.py +2 -8
  513. scipy/sparse/linalg/_matfuncs.py +1 -1
  514. scipy/sparse/linalg/_norm.py +1 -1
  515. scipy/sparse/linalg/_propack/_cpropack.cp313t-win_amd64.dll.a +0 -0
  516. scipy/sparse/linalg/_propack/_cpropack.cp313t-win_amd64.pyd +0 -0
  517. scipy/sparse/linalg/_propack/_dpropack.cp313t-win_amd64.dll.a +0 -0
  518. scipy/sparse/linalg/_propack/_dpropack.cp313t-win_amd64.pyd +0 -0
  519. scipy/sparse/linalg/_propack/_spropack.cp313t-win_amd64.dll.a +0 -0
  520. scipy/sparse/linalg/_propack/_spropack.cp313t-win_amd64.pyd +0 -0
  521. scipy/sparse/linalg/_propack/_zpropack.cp313t-win_amd64.dll.a +0 -0
  522. scipy/sparse/linalg/_propack/_zpropack.cp313t-win_amd64.pyd +0 -0
  523. scipy/sparse/linalg/_special_sparse_arrays.py +39 -38
  524. scipy/sparse/linalg/tests/test_pydata_sparse.py +14 -0
  525. scipy/sparse/tests/test_arithmetic1d.py +5 -2
  526. scipy/sparse/tests/test_base.py +214 -42
  527. scipy/sparse/tests/test_common1d.py +7 -7
  528. scipy/sparse/tests/test_construct.py +1 -1
  529. scipy/sparse/tests/test_coo.py +272 -4
  530. scipy/sparse/tests/test_sparsetools.py +5 -0
  531. scipy/sparse/tests/test_sputils.py +36 -7
  532. scipy/spatial/_ckdtree.cp313t-win_amd64.dll.a +0 -0
  533. scipy/spatial/_ckdtree.cp313t-win_amd64.pyd +0 -0
  534. scipy/spatial/_distance_pybind.cp313t-win_amd64.dll.a +0 -0
  535. scipy/spatial/_distance_pybind.cp313t-win_amd64.pyd +0 -0
  536. scipy/spatial/_distance_wrap.cp313t-win_amd64.dll.a +0 -0
  537. scipy/spatial/_distance_wrap.cp313t-win_amd64.pyd +0 -0
  538. scipy/spatial/_hausdorff.cp313t-win_amd64.dll.a +0 -0
  539. scipy/spatial/_hausdorff.cp313t-win_amd64.pyd +0 -0
  540. scipy/spatial/_qhull.cp313t-win_amd64.dll.a +0 -0
  541. scipy/spatial/_qhull.cp313t-win_amd64.pyd +0 -0
  542. scipy/spatial/_voronoi.cp313t-win_amd64.dll.a +0 -0
  543. scipy/spatial/_voronoi.cp313t-win_amd64.pyd +0 -0
  544. scipy/spatial/distance.py +49 -42
  545. scipy/spatial/tests/test_distance.py +15 -1
  546. scipy/spatial/tests/test_kdtree.py +1 -0
  547. scipy/spatial/tests/test_qhull.py +7 -2
  548. scipy/spatial/transform/__init__.py +5 -3
  549. scipy/spatial/transform/_rigid_transform.cp313t-win_amd64.dll.a +0 -0
  550. scipy/spatial/transform/_rigid_transform.cp313t-win_amd64.pyd +0 -0
  551. scipy/spatial/transform/_rotation.cp313t-win_amd64.dll.a +0 -0
  552. scipy/spatial/transform/_rotation.cp313t-win_amd64.pyd +0 -0
  553. scipy/spatial/transform/tests/test_rigid_transform.py +1221 -0
  554. scipy/spatial/transform/tests/test_rotation.py +1213 -832
  555. scipy/spatial/transform/tests/test_rotation_groups.py +3 -3
  556. scipy/spatial/transform/tests/test_rotation_spline.py +29 -8
  557. scipy/special/__init__.py +1 -47
  558. scipy/special/_add_newdocs.py +34 -772
  559. scipy/special/_basic.py +22 -25
  560. scipy/special/_comb.cp313t-win_amd64.dll.a +0 -0
  561. scipy/special/_comb.cp313t-win_amd64.pyd +0 -0
  562. scipy/special/_ellip_harm_2.cp313t-win_amd64.dll.a +0 -0
  563. scipy/special/_ellip_harm_2.cp313t-win_amd64.pyd +0 -0
  564. scipy/special/_gufuncs.cp313t-win_amd64.dll.a +0 -0
  565. scipy/special/_gufuncs.cp313t-win_amd64.pyd +0 -0
  566. scipy/special/_logsumexp.py +67 -58
  567. scipy/special/_orthogonal.pyi +1 -1
  568. scipy/special/_specfun.cp313t-win_amd64.dll.a +0 -0
  569. scipy/special/_specfun.cp313t-win_amd64.pyd +0 -0
  570. scipy/special/_special_ufuncs.cp313t-win_amd64.dll.a +0 -0
  571. scipy/special/_special_ufuncs.cp313t-win_amd64.pyd +0 -0
  572. scipy/special/_spherical_bessel.py +4 -4
  573. scipy/special/_support_alternative_backends.py +212 -119
  574. scipy/special/_test_internal.cp313t-win_amd64.dll.a +0 -0
  575. scipy/special/_test_internal.cp313t-win_amd64.pyd +0 -0
  576. scipy/special/_testutils.py +4 -4
  577. scipy/special/_ufuncs.cp313t-win_amd64.dll.a +0 -0
  578. scipy/special/_ufuncs.cp313t-win_amd64.pyd +0 -0
  579. scipy/special/_ufuncs.pyi +1 -0
  580. scipy/special/_ufuncs.pyx +215 -1400
  581. scipy/special/_ufuncs_cxx.cp313t-win_amd64.dll.a +0 -0
  582. scipy/special/_ufuncs_cxx.cp313t-win_amd64.pyd +0 -0
  583. scipy/special/_ufuncs_cxx.pxd +2 -15
  584. scipy/special/_ufuncs_cxx.pyx +5 -44
  585. scipy/special/_ufuncs_cxx_defs.h +2 -16
  586. scipy/special/_ufuncs_defs.h +0 -8
  587. scipy/special/cython_special.cp313t-win_amd64.dll.a +0 -0
  588. scipy/special/cython_special.cp313t-win_amd64.pyd +0 -0
  589. scipy/special/cython_special.pxd +1 -1
  590. scipy/special/tests/_cython_examples/meson.build +10 -1
  591. scipy/special/tests/test_basic.py +153 -20
  592. scipy/special/tests/test_boost_ufuncs.py +3 -0
  593. scipy/special/tests/test_cdflib.py +35 -11
  594. scipy/special/tests/test_gammainc.py +16 -0
  595. scipy/special/tests/test_hyp2f1.py +2 -2
  596. scipy/special/tests/test_log1mexp.py +85 -0
  597. scipy/special/tests/test_logsumexp.py +206 -64
  598. scipy/special/tests/test_mpmath.py +1 -0
  599. scipy/special/tests/test_nan_inputs.py +1 -1
  600. scipy/special/tests/test_orthogonal.py +17 -18
  601. scipy/special/tests/test_sf_error.py +3 -2
  602. scipy/special/tests/test_sph_harm.py +6 -7
  603. scipy/special/tests/test_support_alternative_backends.py +211 -76
  604. scipy/stats/__init__.py +4 -1
  605. scipy/stats/_ansari_swilk_statistics.cp313t-win_amd64.dll.a +0 -0
  606. scipy/stats/_ansari_swilk_statistics.cp313t-win_amd64.pyd +0 -0
  607. scipy/stats/_axis_nan_policy.py +5 -12
  608. scipy/stats/_biasedurn.cp313t-win_amd64.dll.a +0 -0
  609. scipy/stats/_biasedurn.cp313t-win_amd64.pyd +0 -0
  610. scipy/stats/_continued_fraction.py +387 -0
  611. scipy/stats/_continuous_distns.py +277 -310
  612. scipy/stats/_correlation.py +1 -1
  613. scipy/stats/_covariance.py +6 -3
  614. scipy/stats/_discrete_distns.py +39 -32
  615. scipy/stats/_distn_infrastructure.py +39 -12
  616. scipy/stats/_distribution_infrastructure.py +900 -238
  617. scipy/stats/_entropy.py +9 -10
  618. scipy/{_lib → stats}/_finite_differences.py +1 -1
  619. scipy/stats/_hypotests.py +83 -50
  620. scipy/stats/_kde.py +53 -49
  621. scipy/stats/_ksstats.py +1 -1
  622. scipy/stats/_levy_stable/__init__.py +7 -15
  623. scipy/stats/_levy_stable/levyst.cp313t-win_amd64.dll.a +0 -0
  624. scipy/stats/_levy_stable/levyst.cp313t-win_amd64.pyd +0 -0
  625. scipy/stats/_morestats.py +118 -73
  626. scipy/stats/_mstats_basic.py +13 -17
  627. scipy/stats/_mstats_extras.py +8 -8
  628. scipy/stats/_multivariate.py +89 -113
  629. scipy/stats/_new_distributions.py +97 -20
  630. scipy/stats/_page_trend_test.py +12 -5
  631. scipy/stats/_probability_distribution.py +265 -43
  632. scipy/stats/_qmc.py +14 -9
  633. scipy/stats/_qmc_cy.cp313t-win_amd64.dll.a +0 -0
  634. scipy/stats/_qmc_cy.cp313t-win_amd64.pyd +0 -0
  635. scipy/stats/_qmvnt.py +16 -95
  636. scipy/stats/_qmvnt_cy.cp313t-win_amd64.dll.a +0 -0
  637. scipy/stats/_qmvnt_cy.cp313t-win_amd64.pyd +0 -0
  638. scipy/stats/_quantile.py +335 -0
  639. scipy/stats/_rcont/rcont.cp313t-win_amd64.dll.a +0 -0
  640. scipy/stats/_rcont/rcont.cp313t-win_amd64.pyd +0 -0
  641. scipy/stats/_resampling.py +4 -29
  642. scipy/stats/_sampling.py +1 -1
  643. scipy/stats/_sobol.cp313t-win_amd64.dll.a +0 -0
  644. scipy/stats/_sobol.cp313t-win_amd64.pyd +0 -0
  645. scipy/stats/_stats.cp313t-win_amd64.dll.a +0 -0
  646. scipy/stats/_stats.cp313t-win_amd64.pyd +0 -0
  647. scipy/stats/_stats_mstats_common.py +21 -2
  648. scipy/stats/_stats_py.py +550 -476
  649. scipy/stats/_stats_pythran.cp313t-win_amd64.dll.a +0 -0
  650. scipy/stats/_stats_pythran.cp313t-win_amd64.pyd +0 -0
  651. scipy/stats/_unuran/unuran_wrapper.cp313t-win_amd64.dll.a +0 -0
  652. scipy/stats/_unuran/unuran_wrapper.cp313t-win_amd64.pyd +0 -0
  653. scipy/stats/_unuran/unuran_wrapper.pyi +2 -1
  654. scipy/stats/_variation.py +6 -8
  655. scipy/stats/_wilcoxon.py +13 -7
  656. scipy/stats/tests/common_tests.py +6 -4
  657. scipy/stats/tests/test_axis_nan_policy.py +62 -24
  658. scipy/stats/tests/test_continued_fraction.py +173 -0
  659. scipy/stats/tests/test_continuous.py +379 -60
  660. scipy/stats/tests/test_continuous_basic.py +18 -12
  661. scipy/stats/tests/test_discrete_basic.py +14 -8
  662. scipy/stats/tests/test_discrete_distns.py +16 -16
  663. scipy/stats/tests/test_distributions.py +95 -75
  664. scipy/stats/tests/test_entropy.py +40 -48
  665. scipy/stats/tests/test_fit.py +4 -3
  666. scipy/stats/tests/test_hypotests.py +153 -24
  667. scipy/stats/tests/test_kdeoth.py +109 -41
  668. scipy/stats/tests/test_marray.py +289 -0
  669. scipy/stats/tests/test_morestats.py +79 -47
  670. scipy/stats/tests/test_mstats_basic.py +3 -3
  671. scipy/stats/tests/test_multivariate.py +434 -83
  672. scipy/stats/tests/test_qmc.py +13 -10
  673. scipy/stats/tests/test_quantile.py +199 -0
  674. scipy/stats/tests/test_rank.py +119 -112
  675. scipy/stats/tests/test_resampling.py +47 -56
  676. scipy/stats/tests/test_sampling.py +9 -4
  677. scipy/stats/tests/test_stats.py +799 -939
  678. scipy/stats/tests/test_variation.py +8 -6
  679. scipy/version.py +2 -2
  680. scipy-1.16.0rc2.dist-info/DELVEWHEEL +2 -0
  681. {scipy-1.15.3.dist-info → scipy-1.16.0rc2.dist-info}/LICENSE.txt +4 -4
  682. {scipy-1.15.3.dist-info → scipy-1.16.0rc2.dist-info}/METADATA +11 -11
  683. {scipy-1.15.3.dist-info → scipy-1.16.0rc2.dist-info}/RECORD +685 -693
  684. scipy/_lib/array_api_extra/_funcs.py +0 -484
  685. scipy/_lib/array_api_extra/_typing.py +0 -8
  686. scipy/interpolate/_bspl.cp313t-win_amd64.dll.a +0 -0
  687. scipy/interpolate/_bspl.cp313t-win_amd64.pyd +0 -0
  688. scipy/optimize/_cobyla.cp313t-win_amd64.dll.a +0 -0
  689. scipy/optimize/_cobyla.cp313t-win_amd64.pyd +0 -0
  690. scipy/optimize/_cython_nnls.cp313t-win_amd64.dll.a +0 -0
  691. scipy/optimize/_cython_nnls.cp313t-win_amd64.pyd +0 -0
  692. scipy/optimize/_slsqp.cp313t-win_amd64.dll.a +0 -0
  693. scipy/optimize/_slsqp.cp313t-win_amd64.pyd +0 -0
  694. scipy/spatial/qhull_src/COPYING.txt +0 -38
  695. scipy/special/libsf_error_state.dll +0 -0
  696. scipy/special/libsf_error_state.dll.a +0 -0
  697. scipy/special/tests/test_log_softmax.py +0 -109
  698. scipy/special/tests/test_xsf_cuda.py +0 -114
  699. scipy/special/xsf/binom.h +0 -89
  700. scipy/special/xsf/cdflib.h +0 -100
  701. scipy/special/xsf/cephes/airy.h +0 -307
  702. scipy/special/xsf/cephes/besselpoly.h +0 -51
  703. scipy/special/xsf/cephes/beta.h +0 -257
  704. scipy/special/xsf/cephes/cbrt.h +0 -131
  705. scipy/special/xsf/cephes/chbevl.h +0 -85
  706. scipy/special/xsf/cephes/chdtr.h +0 -193
  707. scipy/special/xsf/cephes/const.h +0 -87
  708. scipy/special/xsf/cephes/ellie.h +0 -293
  709. scipy/special/xsf/cephes/ellik.h +0 -251
  710. scipy/special/xsf/cephes/ellpe.h +0 -107
  711. scipy/special/xsf/cephes/ellpk.h +0 -117
  712. scipy/special/xsf/cephes/expn.h +0 -260
  713. scipy/special/xsf/cephes/gamma.h +0 -398
  714. scipy/special/xsf/cephes/hyp2f1.h +0 -596
  715. scipy/special/xsf/cephes/hyperg.h +0 -361
  716. scipy/special/xsf/cephes/i0.h +0 -149
  717. scipy/special/xsf/cephes/i1.h +0 -158
  718. scipy/special/xsf/cephes/igam.h +0 -421
  719. scipy/special/xsf/cephes/igam_asymp_coeff.h +0 -195
  720. scipy/special/xsf/cephes/igami.h +0 -313
  721. scipy/special/xsf/cephes/j0.h +0 -225
  722. scipy/special/xsf/cephes/j1.h +0 -198
  723. scipy/special/xsf/cephes/jv.h +0 -715
  724. scipy/special/xsf/cephes/k0.h +0 -164
  725. scipy/special/xsf/cephes/k1.h +0 -163
  726. scipy/special/xsf/cephes/kn.h +0 -243
  727. scipy/special/xsf/cephes/lanczos.h +0 -112
  728. scipy/special/xsf/cephes/ndtr.h +0 -275
  729. scipy/special/xsf/cephes/poch.h +0 -85
  730. scipy/special/xsf/cephes/polevl.h +0 -167
  731. scipy/special/xsf/cephes/psi.h +0 -194
  732. scipy/special/xsf/cephes/rgamma.h +0 -111
  733. scipy/special/xsf/cephes/scipy_iv.h +0 -811
  734. scipy/special/xsf/cephes/shichi.h +0 -248
  735. scipy/special/xsf/cephes/sici.h +0 -224
  736. scipy/special/xsf/cephes/sindg.h +0 -221
  737. scipy/special/xsf/cephes/tandg.h +0 -139
  738. scipy/special/xsf/cephes/trig.h +0 -58
  739. scipy/special/xsf/cephes/unity.h +0 -186
  740. scipy/special/xsf/cephes/zeta.h +0 -172
  741. scipy/special/xsf/config.h +0 -304
  742. scipy/special/xsf/digamma.h +0 -205
  743. scipy/special/xsf/error.h +0 -57
  744. scipy/special/xsf/evalpoly.h +0 -47
  745. scipy/special/xsf/expint.h +0 -266
  746. scipy/special/xsf/hyp2f1.h +0 -694
  747. scipy/special/xsf/iv_ratio.h +0 -173
  748. scipy/special/xsf/lambertw.h +0 -150
  749. scipy/special/xsf/loggamma.h +0 -163
  750. scipy/special/xsf/sici.h +0 -200
  751. scipy/special/xsf/tools.h +0 -427
  752. scipy/special/xsf/trig.h +0 -164
  753. scipy/special/xsf/wright_bessel.h +0 -843
  754. scipy/special/xsf/zlog1.h +0 -35
  755. scipy/stats/_mvn.cp313t-win_amd64.dll.a +0 -0
  756. scipy/stats/_mvn.cp313t-win_amd64.pyd +0 -0
  757. scipy-1.15.3.dist-info/DELVEWHEEL +0 -2
  758. /scipy-1.15.3-cp313-cp313t-win_amd64.whl → /scipy-1.16.0rc2-cp313-cp313t-win_amd64.whl +0 -0
  759. {scipy-1.15.3.dist-info → scipy-1.16.0rc2.dist-info}/WHEEL +0 -0
@@ -1,5 +1,9 @@
1
+ import math
2
+ import cmath
1
3
  import warnings
2
4
 
5
+ from itertools import product
6
+
3
7
  from scipy._lib import _pep440
4
8
  import numpy as np
5
9
  from numpy.testing import (
@@ -9,22 +13,28 @@ import pytest
9
13
  from pytest import raises as assert_raises
10
14
  from scipy._lib._array_api import (
11
15
  xp_assert_close, xp_assert_equal,
12
- assert_array_almost_equal,
16
+ assert_array_almost_equal, xp_size, xp_default_dtype, is_numpy
13
17
  )
14
18
 
15
- from numpy import array, spacing, sin, pi, sort, sqrt
19
+ from numpy import array, spacing, sin, pi
16
20
  from scipy.signal import (argrelextrema, BadCoefficients, bessel, besselap, bilinear,
17
21
  buttap, butter, buttord, cheb1ap, cheb1ord, cheb2ap,
18
22
  cheb2ord, cheby1, cheby2, ellip, ellipap, ellipord,
19
23
  firwin, freqs_zpk, freqs, freqz, freqz_zpk,
20
24
  gammatone, group_delay, iircomb, iirdesign, iirfilter,
21
25
  iirnotch, iirpeak, lp2bp, lp2bs, lp2hp, lp2lp, normalize,
22
- medfilt, order_filter,
23
26
  sos2tf, sos2zpk, sosfreqz, freqz_sos, tf2sos, tf2zpk, zpk2sos,
24
27
  zpk2tf, bilinear_zpk, lp2lp_zpk, lp2hp_zpk, lp2bp_zpk,
25
28
  lp2bs_zpk)
26
29
  from scipy.signal._filter_design import (_cplxreal, _cplxpair, _norm_factor,
27
30
  _bessel_poly, _bessel_zeros)
31
+ from scipy.signal._filter_design import _logspace
32
+ from scipy.signal import _polyutils as _pu
33
+ from scipy.signal._polyutils import _sort_cmplx
34
+
35
+ skip_xp_backends = pytest.mark.skip_xp_backends
36
+ xfail_xp_backends = pytest.mark.xfail_xp_backends
37
+
28
38
 
29
39
  try:
30
40
  import mpmath
@@ -168,26 +178,33 @@ class TestCplxReal:
168
178
 
169
179
  class TestTf2zpk:
170
180
 
171
- @pytest.mark.parametrize('dt', (np.float64, np.complex128))
172
- def test_simple(self, dt):
173
- z_r = np.array([0.5, -0.5])
174
- p_r = np.array([1.j / np.sqrt(2), -1.j / np.sqrt(2)])
181
+ @skip_xp_backends(
182
+ cpu_only=True, reason="XXX zpk2sos is numpy-only", exceptions=['cupy']
183
+ )
184
+ @skip_xp_backends("dask.array", reason="https://github.com/dask/dask/issues/11883")
185
+ @pytest.mark.parametrize('dt', ('float64', 'complex128'))
186
+ def test_simple(self, dt, xp):
187
+ dtyp = getattr(xp, dt)
188
+
189
+ z_r = xp.asarray([0.5, -0.5])
190
+ p_r = xp.asarray([1.j / math.sqrt(2), -1.j / math.sqrt(2)])
175
191
  # Sort the zeros/poles so that we don't fail the test if the order
176
192
  # changes
177
- z_r.sort()
178
- p_r.sort()
179
- b = np.poly(z_r).astype(dt)
180
- a = np.poly(p_r).astype(dt)
193
+ z_r = _sort_cmplx(z_r, xp=xp)
194
+ p_r = _sort_cmplx(p_r, xp=xp)
195
+
196
+ b = xp.astype(_pu.poly(z_r, xp=xp), dtyp)
197
+ a = xp.astype(_pu.poly(p_r, xp=xp), dtyp)
181
198
 
182
199
  z, p, k = tf2zpk(b, a)
183
- z.sort()
200
+ z = _sort_cmplx(z, xp=xp)
184
201
  # The real part of `p` is ~0.0, so sort by imaginary part
185
- p = p[np.argsort(p.imag)]
202
+ p = p[xp.argsort(xp.imag(p))]
186
203
 
187
204
  assert_array_almost_equal(z, z_r)
188
205
  assert_array_almost_equal(p, p_r)
189
- assert_array_almost_equal(k, 1.)
190
- assert k.dtype == dt
206
+ assert math.isclose(xp.real(k), 1.)
207
+ assert k.dtype == dtyp
191
208
 
192
209
  def test_bad_filter(self):
193
210
  # Regression test for #651: better handling of badly conditioned
@@ -199,47 +216,91 @@ class TestTf2zpk:
199
216
 
200
217
  class TestZpk2Tf:
201
218
 
202
- def test_identity(self):
219
+ def test_identity(self, xp):
203
220
  """Test the identity transfer function."""
204
- z = []
205
- p = []
221
+ z = xp.asarray([])
222
+ p = xp.asarray([])
206
223
  k = 1.
207
224
  b, a = zpk2tf(z, p, k)
208
- b_r = np.array([1.]) # desired result
209
- a_r = np.array([1.]) # desired result
225
+ b_r = xp.asarray([1.]) # desired result
226
+ a_r = xp.asarray([1.]) # desired result
210
227
  # The test for the *type* of the return values is a regression
211
228
  # test for ticket #1095. In the case p=[], zpk2tf used to
212
229
  # return the scalar 1.0 instead of array([1.0]).
213
230
  xp_assert_equal(b, b_r)
214
- assert isinstance(b, np.ndarray)
215
231
  xp_assert_equal(a, a_r)
216
- assert isinstance(a, np.ndarray)
232
+ if is_numpy(xp):
233
+ assert isinstance(b, np.ndarray)
234
+ assert isinstance(a, np.ndarray)
235
+
236
+ @skip_xp_backends("dask.array", reason="https://github.com/dask/dask/issues/11883")
237
+ @skip_xp_backends(cpu_only=True, reason="XXX zpk2sos is numpy-only")
238
+ def test_conj_pair(self, xp):
239
+ # conjugate pairs give real-coeff num & den
240
+ z = xp.asarray([1j, -1j, 2j, -2j])
241
+ # shouldn't need elements of pairs to be adjacent
242
+ p = xp.asarray([1+1j, 3-100j, 3+100j, 1-1j])
243
+ k = 23
244
+
245
+ # np.poly should do the right thing, but be explicit about
246
+ # taking real part
247
+ z_np, p_np = map(np.asarray, (z, p))
248
+ b_np = k * np.poly(z_np).real
249
+ a_np = np.poly(p_np).real
250
+ b, a = map(xp.asarray, (b_np, a_np))
251
+
252
+ bp, ap = zpk2tf(z, p, k)
253
+
254
+ xp_assert_close(b, bp)
255
+ xp_assert_close(a, ap)
256
+
257
+ assert xp.isdtype(bp.dtype, 'real floating')
258
+ assert xp.isdtype(ap.dtype, 'real floating')
259
+
260
+ @skip_xp_backends("dask.array", reason="https://github.com/dask/dask/issues/11883")
261
+ @skip_xp_backends(
262
+ cpu_only=True, reason="XXX zpk2sos is numpy-only", exceptions=['cupy']
263
+ )
264
+ def test_complexk(self, xp):
265
+ # regression: z, p real, k complex k gave real b, a
266
+ b, a = xp.asarray([1j, 1j]), xp.asarray([1.0, 2])
267
+ z, p, k = tf2zpk(b, a)
268
+ xp_assert_close(k, xp.asarray(1j), check_0d=False)
269
+ bp, ap = zpk2tf(z, p, k)
270
+ xp_assert_close(b, bp)
271
+ xp_assert_close(a, ap)
217
272
 
218
273
 
274
+ @skip_xp_backends("jax.numpy", reason='no eig in JAX on GPU.')
219
275
  class TestSos2Zpk:
220
276
 
221
- def test_basic(self):
277
+ @skip_xp_backends("dask.array", reason="it https://github.com/dask/dask/issues/11883")
278
+ def test_basic(self, xp):
222
279
  sos = [[1, 0, 1, 1, 0, -0.81],
223
280
  [1, 0, 0, 1, 0, +0.49]]
281
+ sos = xp.asarray(sos)
224
282
  z, p, k = sos2zpk(sos)
225
- z2 = [1j, -1j, 0, 0]
226
- p2 = [0.9, -0.9, 0.7j, -0.7j]
227
- k2 = 1
228
- assert_array_almost_equal(sort(z), sort(z2), decimal=4)
229
- assert_array_almost_equal(sort(p), sort(p2), decimal=4)
230
- assert_array_almost_equal(k, k2)
283
+ z2 = xp.asarray([1j, -1j, 0, 0])
284
+ p2 = xp.asarray([0.9, -0.9, 0.7j, -0.7j])
285
+ k2 = 1.
286
+ assert_array_almost_equal(_sort_cmplx(z, xp), _sort_cmplx(z2, xp), decimal=4)
287
+ assert_array_almost_equal(_sort_cmplx(p, xp), _sort_cmplx(p2, xp), decimal=4)
288
+ assert math.isclose(k, k2)
231
289
 
232
290
  sos = [[1.00000, +0.61803, 1.0000, 1.00000, +0.60515, 0.95873],
233
291
  [1.00000, -1.61803, 1.0000, 1.00000, -1.58430, 0.95873],
234
292
  [1.00000, +1.00000, 0.0000, 1.00000, +0.97915, 0.00000]]
293
+ sos = xp.asarray(sos)
235
294
  z, p, k = sos2zpk(sos)
236
295
  z2 = [-0.3090 + 0.9511j, -0.3090 - 0.9511j, 0.8090 + 0.5878j,
237
296
  0.8090 - 0.5878j, -1.0000 + 0.0000j, 0]
238
297
  p2 = [-0.3026 + 0.9312j, -0.3026 - 0.9312j, 0.7922 + 0.5755j,
239
298
  0.7922 - 0.5755j, -0.9791 + 0.0000j, 0]
299
+ z2 = xp.asarray(z2)
300
+ p2 = xp.asarray(p2)
240
301
  k2 = 1
241
- assert_array_almost_equal(sort(z), sort(z2), decimal=4)
242
- assert_array_almost_equal(sort(p), sort(p2), decimal=4)
302
+ assert_array_almost_equal(_sort_cmplx(z, xp), _sort_cmplx(z2, xp), decimal=4)
303
+ assert_array_almost_equal(_sort_cmplx(p, xp), _sort_cmplx(p2, xp), decimal=4)
243
304
 
244
305
  sos = array([[1, 2, 3, 1, 0.2, 0.3],
245
306
  [4, 5, 6, 1, 0.4, 0.5]])
@@ -247,138 +308,164 @@ class TestSos2Zpk:
247
308
  -0.625 - 1.05326872164704j, -0.625 + 1.05326872164704j])
248
309
  p = array([-0.2 - 0.678232998312527j, -0.2 + 0.678232998312527j,
249
310
  -0.1 - 0.538516480713450j, -0.1 + 0.538516480713450j])
311
+ sos, z, p = map(xp.asarray, (sos, z, p))
250
312
  k = 4
251
313
  z2, p2, k2 = sos2zpk(sos)
252
- xp_assert_close(_cplxpair(z2), z)
253
- xp_assert_close(_cplxpair(p2), p)
314
+
315
+ xp_assert_close(_sort_cmplx(z2, xp=xp), _sort_cmplx(z, xp=xp))
316
+ xp_assert_close(_sort_cmplx(p2, xp=xp), _sort_cmplx(p, xp=xp))
254
317
  assert k2 == k
255
318
 
256
319
  @pytest.mark.thread_unsafe
257
- def test_fewer_zeros(self):
320
+ def test_fewer_zeros(self, xp):
258
321
  """Test not the expected number of p/z (effectively at origin)."""
259
322
  sos = butter(3, 0.1, output='sos')
323
+ sos = xp.asarray(sos) # XXX convert butter
260
324
  z, p, k = sos2zpk(sos)
261
- assert len(z) == 4
262
- assert len(p) == 4
325
+ assert z.shape[0] == 4
326
+ assert p.shape[0] == 4
263
327
 
264
328
  sos = butter(12, [5., 30.], 'bandpass', fs=1200., analog=False,
265
329
  output='sos')
330
+ xp = xp.asarray(sos)
266
331
  with pytest.warns(BadCoefficients, match='Badly conditioned'):
267
332
  z, p, k = sos2zpk(sos)
268
- assert len(z) == 24
269
- assert len(p) == 24
333
+ assert z.shape[0] == 24
334
+ assert p.shape[0] == 24
270
335
 
271
336
 
337
+ @skip_xp_backends(
338
+ cpu_only=True, reason="XXX zpk2sos is numpy-only", exceptions=['cupy']
339
+ )
272
340
  class TestSos2Tf:
273
341
 
274
- def test_basic(self):
275
- sos = [[1, 1, 1, 1, 0, -1],
342
+ def test_basic(self, xp):
343
+ sos = [[1.0, 1, 1, 1, 0, -1],
276
344
  [-2, 3, 1, 1, 10, 1]]
345
+ sos = xp.asarray(sos)
277
346
  b, a = sos2tf(sos)
278
- assert_array_almost_equal(b, [-2, 1, 2, 4, 1])
279
- assert_array_almost_equal(a, [1, 10, 0, -10, -1])
347
+ assert_array_almost_equal(b, xp.asarray([-2.0, 1, 2, 4, 1]))
348
+ assert_array_almost_equal(a, xp.asarray([1.0, 10, 0, -10, -1]))
280
349
 
281
350
 
351
+ @skip_xp_backends(cpu_only=True, reason="XXX zpk2sos is numpy-only")
282
352
  class TestTf2Sos:
283
353
 
284
- def test_basic(self):
285
- num = [2, 16, 44, 56, 32]
286
- den = [3, 3, -15, 18, -12]
354
+ def test_basic(self, xp):
355
+ num = xp.asarray([2., 16, 44, 56, 32])
356
+ den = xp.asarray([3., 3, -15, 18, -12])
287
357
  sos = tf2sos(num, den)
288
358
  sos2 = [[0.6667, 4.0000, 5.3333, 1.0000, +2.0000, -4.0000],
289
359
  [1.0000, 2.0000, 2.0000, 1.0000, -1.0000, +1.0000]]
360
+ sos2 = xp.asarray(sos2)
290
361
  assert_array_almost_equal(sos, sos2, decimal=4)
291
362
 
292
- b = [1, -3, 11, -27, 18]
293
- a = [16, 12, 2, -4, -1]
363
+ b = xp.asarray([1.0, -3, 11, -27, 18])
364
+ a = xp.asarray([16.0, 12, 2, -4, -1])
294
365
  sos = tf2sos(b, a)
295
366
  sos2 = [[0.0625, -0.1875, 0.1250, 1.0000, -0.2500, -0.1250],
296
367
  [1.0000, +0.0000, 9.0000, 1.0000, +1.0000, +0.5000]]
297
- # assert_array_almost_equal(sos, sos2, decimal=4)
368
+ sos2 = xp.asarray(sos2)
369
+ #assert_array_almost_equal(sos, sos2, decimal=4)
298
370
 
299
371
  @pytest.mark.parametrize('b, a, analog, sos',
300
- [([1], [1], False, [[1., 0., 0., 1., 0., 0.]]),
301
- ([1], [1], True, [[0., 0., 1., 0., 0., 1.]]),
302
- ([1], [1., 0., -1.01, 0, 0.01], False,
372
+ [([1.0], [1.0], False, [[1., 0., 0., 1., 0., 0.]]),
373
+ ([1.0], [1.0], True, [[0., 0., 1., 0., 0., 1.]]),
374
+ ([1.0], [1., 0., -1.01, 0, 0.01], False,
303
375
  [[1., 0., 0., 1., 0., -0.01],
304
376
  [1., 0., 0., 1., 0., -1]]),
305
- ([1], [1., 0., -1.01, 0, 0.01], True,
377
+ ([1.0], [1., 0., -1.01, 0, 0.01], True,
306
378
  [[0., 0., 1., 1., 0., -1],
307
379
  [0., 0., 1., 1., 0., -0.01]])])
308
- def test_analog(self, b, a, analog, sos):
380
+ def test_analog(self, b, a, analog, sos, xp):
381
+ b, a, sos = map(xp.asarray, (b, a, sos))
309
382
  sos2 = tf2sos(b, a, analog=analog)
310
383
  assert_array_almost_equal(sos, sos2, decimal=4)
311
384
 
312
385
 
386
+ @skip_xp_backends(
387
+ cpu_only=True, reason="XXX zpk2sos is numpy-only", exceptions=['cupy']
388
+ )
313
389
  class TestZpk2Sos:
314
390
 
315
- @pytest.mark.parametrize('dt', 'fdgFDG')
391
+ # @pytest.mark.parametrize('dt', 'fdgFDG')
392
+ # XXX: quietly remove float128 and complex256
393
+ @pytest.mark.parametrize('dt', ['float32', 'float64', 'complex64', 'complex128'])
316
394
  @pytest.mark.parametrize('pairing, analog',
317
395
  [('nearest', False),
318
396
  ('keep_odd', False),
319
397
  ('minimal', False),
320
398
  ('minimal', True)])
321
- def test_dtypes(self, dt, pairing, analog):
322
- z = np.array([-1, -1]).astype(dt)
323
- ct = dt.upper() # the poles have to be complex
324
- p = np.array([0.57149 + 0.29360j, 0.57149 - 0.29360j]).astype(ct)
325
- k = np.array(1).astype(dt)
399
+ def test_dtypes(self, dt, pairing, analog, xp):
400
+ dtype = getattr(xp, dt)
401
+ # the poles have to be complex
402
+ cdtype = (xp.empty(1, dtype=dtype) + 1j*xp.empty(1, dtype=dtype)).dtype
403
+
404
+ z = xp.asarray([-1, -1], dtype=dtype)
405
+ p = xp.asarray([0.57149 + 0.29360j, 0.57149 - 0.29360j], dtype=cdtype)
406
+ k = xp.asarray(1, dtype=dtype)
326
407
  sos = zpk2sos(z, p, k, pairing=pairing, analog=analog)
327
- sos2 = [[1, 2, 1, 1, -1.14298, 0.41280]] # octave & MATLAB
408
+ # octave & MATLAB
409
+ sos2 = xp.asarray([[1, 2, 1, 1, -1.14298, 0.41280]], dtype=dtype)
328
410
  assert_array_almost_equal(sos, sos2, decimal=4)
329
411
 
330
- def test_basic(self):
412
+ def test_basic(self, xp):
331
413
  for pairing in ('nearest', 'keep_odd'):
332
414
  #
333
415
  # Cases that match octave
334
416
  #
335
417
 
336
- z = [-1, -1]
337
- p = [0.57149 + 0.29360j, 0.57149 - 0.29360j]
418
+ z = xp.asarray([-1.0, -1.0])
419
+ p = xp.asarray([0.57149 + 0.29360j, 0.57149 - 0.29360j])
338
420
  k = 1
339
421
  sos = zpk2sos(z, p, k, pairing=pairing)
340
- sos2 = [[1, 2, 1, 1, -1.14298, 0.41280]] # octave & MATLAB
422
+ sos2 = xp.asarray([[1, 2, 1, 1, -1.14298, 0.41280]]) # octave & MATLAB
341
423
  assert_array_almost_equal(sos, sos2, decimal=4)
342
424
 
343
- z = [1j, -1j]
344
- p = [0.9, -0.9, 0.7j, -0.7j]
425
+ z = xp.asarray([1j, -1j])
426
+ p = xp.asarray([0.9, -0.9, 0.7j, -0.7j])
345
427
  k = 1
346
428
  sos = zpk2sos(z, p, k, pairing=pairing)
347
429
  sos2 = [[1, 0, 1, 1, 0, +0.49],
348
430
  [1, 0, 0, 1, 0, -0.81]] # octave
431
+ sos2 = xp.asarray(sos2)
349
432
  # sos2 = [[0, 0, 1, 1, -0.9, 0],
350
433
  # [1, 0, 1, 1, 0.9, 0]] # MATLAB
351
434
  assert_array_almost_equal(sos, sos2, decimal=4)
352
435
 
353
- z = []
354
- p = [0.8, -0.5+0.25j, -0.5-0.25j]
436
+ z = xp.asarray([])
437
+ p = xp.asarray([0.8, -0.5+0.25j, -0.5-0.25j])
355
438
  k = 1.
356
439
  sos = zpk2sos(z, p, k, pairing=pairing)
357
440
  sos2 = [[1., 0., 0., 1., 1., 0.3125],
358
441
  [1., 0., 0., 1., -0.8, 0.]] # octave, MATLAB fails
442
+ sos2 = xp.asarray(sos2)
359
443
  assert_array_almost_equal(sos, sos2, decimal=4)
360
444
 
361
- z = [1., 1., 0.9j, -0.9j]
362
- p = [0.99+0.01j, 0.99-0.01j, 0.1+0.9j, 0.1-0.9j]
445
+ z = xp.asarray([1., 1., 0.9j, -0.9j])
446
+ p = xp.asarray([0.99+0.01j, 0.99-0.01j, 0.1+0.9j, 0.1-0.9j])
363
447
  k = 1
364
448
  sos = zpk2sos(z, p, k, pairing=pairing)
365
449
  sos2 = [[1, 0, 0.81, 1, -0.2, 0.82],
366
450
  [1, -2, 1, 1, -1.98, 0.9802]] # octave
451
+ sos2 = xp.asarray(sos2)
367
452
  # sos2 = [[1, -2, 1, 1, -0.2, 0.82],
368
453
  # [1, 0, 0.81, 1, -1.98, 0.9802]] # MATLAB
369
454
  assert_array_almost_equal(sos, sos2, decimal=4)
370
455
 
371
- z = [0.9+0.1j, 0.9-0.1j, -0.9]
372
- p = [0.75+0.25j, 0.75-0.25j, 0.9]
456
+ z = xp.asarray([0.9+0.1j, 0.9-0.1j, -0.9])
457
+ p = xp.asarray([0.75+0.25j, 0.75-0.25j, 0.9])
373
458
  k = 1
374
459
  sos = zpk2sos(z, p, k, pairing=pairing)
375
460
  if pairing == 'keep_odd':
376
461
  sos2 = [[1, -1.8, 0.82, 1, -1.5, 0.625],
377
462
  [1, 0.9, 0, 1, -0.9, 0]] # octave; MATLAB fails
463
+ sos2 = xp.asarray(sos2)
378
464
  assert_array_almost_equal(sos, sos2, decimal=4)
379
465
  else: # pairing == 'nearest'
380
466
  sos2 = [[1, 0.9, 0, 1, -1.5, 0.625],
381
467
  [1, -1.8, 0.82, 1, -0.9, 0]] # our algorithm
468
+ sos2 = xp.asarray(sos2)
382
469
  assert_array_almost_equal(sos, sos2, decimal=4)
383
470
 
384
471
  #
@@ -389,6 +476,8 @@ class TestZpk2Sos:
389
476
  +0.8090 - 0.5878j, -1.0000 + 0.0000j]
390
477
  p = [-0.3026 + 0.9312j, -0.3026 - 0.9312j, 0.7922 + 0.5755j,
391
478
  +0.7922 - 0.5755j, -0.9791 + 0.0000j]
479
+ z = xp.asarray(z)
480
+ p = xp.asarray(p)
392
481
  k = 1
393
482
  sos = zpk2sos(z, p, k, pairing=pairing)
394
483
  # sos2 = [[1, 0.618, 1, 1, 0.6052, 0.95870],
@@ -397,26 +486,31 @@ class TestZpk2Sos:
397
486
  sos2 = [[1, 1, 0, 1, +0.97915, 0],
398
487
  [1, 0.61803, 1, 1, +0.60515, 0.95873],
399
488
  [1, -1.61803, 1, 1, -1.58430, 0.95873]]
489
+ sos2 = xp.asarray(sos2)
400
490
  assert_array_almost_equal(sos, sos2, decimal=4)
401
491
 
402
492
  z = [-1 - 1.4142j, -1 + 1.4142j,
403
493
  -0.625 - 1.0533j, -0.625 + 1.0533j]
404
494
  p = [-0.2 - 0.6782j, -0.2 + 0.6782j,
405
495
  -0.1 - 0.5385j, -0.1 + 0.5385j]
496
+ z = xp.asarray(z)
497
+ p = xp.asarray(p)
406
498
  k = 4
407
499
  sos = zpk2sos(z, p, k, pairing=pairing)
408
500
  sos2 = [[4, 8, 12, 1, 0.2, 0.3],
409
501
  [1, 1.25, 1.5, 1, 0.4, 0.5]] # MATLAB
502
+ sos2 = xp.asarray(sos2, dtype=xp.float64)
410
503
  # sos2 = [[4, 8, 12, 1, 0.4, 0.5],
411
504
  # [1, 1.25, 1.5, 1, 0.2, 0.3]] # octave
412
505
  xp_assert_close(sos, sos2, rtol=1e-4, atol=1e-4)
413
506
 
414
- z = []
415
- p = [0.2, -0.5+0.25j, -0.5-0.25j]
507
+ z = xp.asarray([])
508
+ p = xp.asarray([0.2, -0.5+0.25j, -0.5-0.25j])
416
509
  k = 1.
417
510
  sos = zpk2sos(z, p, k, pairing=pairing)
418
511
  sos2 = [[1., 0., 0., 1., -0.2, 0.],
419
512
  [1., 0., 0., 1., 1., 0.3125]]
513
+ sos2 = xp.asarray(sos2)
420
514
  # sos2 = [[1., 0., 0., 1., 1., 0.3125],
421
515
  # [1., 0., 0., 1., -0.2, 0]] # octave, MATLAB fails
422
516
  assert_array_almost_equal(sos, sos2, decimal=4)
@@ -425,17 +519,16 @@ class TestZpk2Sos:
425
519
  # "Digital Filters and Signal Processing (1995) p.400:
426
520
  # http://books.google.com/books?id=VZ8uabI1pNMC&lpg=PA400&ots=gRD9pi8Jua&dq=Pole%2Fzero%20pairing%20for%20minimum%20roundoff%20noise%20in%20BSF.&pg=PA400#v=onepage&q=Pole%2Fzero%20pairing%20for%20minimum%20roundoff%20noise%20in%20BSF.&f=false
427
521
 
428
- deg2rad = np.pi / 180.
522
+ deg2rad = xp.pi / 180.
429
523
  k = 1.
430
524
 
431
525
  # first example
432
- thetas = [22.5, 45, 77.5]
433
- mags = [0.8, 0.6, 0.9]
434
- z = np.array([np.exp(theta * deg2rad * 1j) for theta in thetas])
435
- z = np.concatenate((z, np.conj(z)))
436
- p = np.array([mag * np.exp(theta * deg2rad * 1j)
437
- for theta, mag in zip(thetas, mags)])
438
- p = np.concatenate((p, np.conj(p)))
526
+ thetas = xp.asarray([22.5, 45, 77.5])
527
+ mags = xp.asarray([0.8, 0.6, 0.9])
528
+ z = xp.exp(1j * deg2rad * thetas)
529
+ z = xp.concat((z, xp.conj(z)))
530
+ p = xp.exp(1j * deg2rad * thetas) * mags
531
+ p = xp.concat((p, xp.conj(p)))
439
532
  sos = zpk2sos(z, p, k)
440
533
  # sos2 = [[1, -0.43288, 1, 1, -0.38959, 0.81], # octave,
441
534
  # [1, -1.41421, 1, 1, -0.84853, 0.36], # MATLAB fails
@@ -444,12 +537,13 @@ class TestZpk2Sos:
444
537
  sos2 = [[1, -1.41421, 1, 1, -0.84853, 0.36],
445
538
  [1, -1.84776, 1, 1, -1.47821, 0.64],
446
539
  [1, -0.43288, 1, 1, -0.38959, 0.81]]
540
+ sos2 = xp.asarray(sos2)
447
541
  assert_array_almost_equal(sos, sos2, decimal=4)
448
542
 
449
543
  # second example
450
- z = np.array([np.exp(theta * deg2rad * 1j)
451
- for theta in (85., 10.)])
452
- z = np.concatenate((z, np.conj(z), [1, -1]))
544
+ thetas = xp.asarray([85., 10.])
545
+ z = xp.exp(1j * deg2rad * thetas)
546
+ z = xp.concat((z, xp.conj(z), xp.asarray([1.0, -1.0])))
453
547
  sos = zpk2sos(z, p, k)
454
548
 
455
549
  # sos2 = [[1, -0.17431, 1, 1, -0.38959, 0.81], # octave "wrong",
@@ -459,6 +553,7 @@ class TestZpk2Sos:
459
553
  sos2 = [[1, 0, -1, 1, -0.84853, 0.36],
460
554
  [1, -1.96962, 1, 1, -1.47821, 0.64],
461
555
  [1, -0.17431, 1, 1, -0.38959, 0.81]]
556
+ sos2 = xp.asarray(sos2)
462
557
  assert_array_almost_equal(sos, sos2, decimal=4)
463
558
 
464
559
  # these examples are taken from the doc string, and show the
@@ -473,9 +568,10 @@ class TestZpk2Sos:
473
568
  ('minimal',
474
569
  np.array([[0., 1., 1., 0., 1., -0.75],
475
570
  [1., 1., 0.5, 1., -1.6, 0.65]]))])
476
- def test_pairing(self, pairing, sos):
477
- z1 = np.array([-1, -0.5-0.5j, -0.5+0.5j])
478
- p1 = np.array([0.75, 0.8+0.1j, 0.8-0.1j])
571
+ def test_pairing(self, pairing, sos, xp):
572
+ sos = xp.asarray(sos)
573
+ z1 = xp.asarray([-1, -0.5-0.5j, -0.5+0.5j])
574
+ p1 = xp.asarray([0.75, 0.8+0.1j, 0.8-0.1j])
479
575
  sos2 = zpk2sos(z1, p1, 1, pairing=pairing)
480
576
  assert_array_almost_equal(sos, sos2, decimal=4)
481
577
 
@@ -486,14 +582,16 @@ class TestZpk2Sos:
486
582
  ([-0.7071+0.7071j, -0.7071-0.7071j, -0.1j, 0.1j],
487
583
  [[0., 0., 1., 1., 0., 0.01],
488
584
  [0., 0., 1., 1., 1.4142, 1.]])])
489
- def test_analog(self, p, sos_dt):
585
+ def test_analog(self, p, sos_dt, xp):
490
586
  # test `analog` argument
491
587
  # for discrete time, poles closest to unit circle should appear last
492
588
  # for cont. time, poles closest to imaginary axis should appear last
493
- sos2_dt = zpk2sos([], p, 1, pairing='minimal', analog=False)
494
- sos2_ct = zpk2sos([], p, 1, pairing='minimal', analog=True)
589
+ z, p = xp.asarray([]), xp.asarray(p)
590
+ sos_dt = xp.asarray(sos_dt)
591
+ sos2_dt = zpk2sos(z, p, 1, pairing='minimal', analog=False)
592
+ sos2_ct = zpk2sos(z, p, 1, pairing='minimal', analog=True)
495
593
  assert_array_almost_equal(sos_dt, sos2_dt, decimal=4)
496
- assert_array_almost_equal(sos_dt[::-1], sos2_ct, decimal=4)
594
+ assert_array_almost_equal(xp.flip(sos_dt, axis=0), sos2_ct, decimal=4)
497
595
 
498
596
  def test_bad_args(self):
499
597
  with pytest.raises(ValueError, match=r'pairing must be one of'):
@@ -512,45 +610,47 @@ class TestZpk2Sos:
512
610
 
513
611
  class TestFreqs:
514
612
 
515
- def test_basic(self):
516
- _, h = freqs([1.0], [1.0], worN=8)
517
- assert_array_almost_equal(h, np.ones(8))
613
+ def test_basic(self, xp):
614
+ _, h = freqs(xp.asarray([1.0]), xp.asarray([1.0]), worN=8)
615
+ assert_array_almost_equal(h, xp.ones(8))
518
616
 
519
- def test_output(self):
617
+ def test_output(self, xp):
520
618
  # 1st order low-pass filter: H(s) = 1 / (s + 1)
521
- w = [0.1, 1, 10, 100]
522
- num = [1]
523
- den = [1, 1]
619
+ w = xp.asarray([0.1, 1, 10, 100])
620
+ num = xp.asarray([1.])
621
+ den = xp.asarray([1, 1.])
524
622
  w, H = freqs(num, den, worN=w)
525
623
  s = w * 1j
526
624
  expected = 1 / (s + 1)
527
- assert_array_almost_equal(H.real, expected.real)
528
- assert_array_almost_equal(H.imag, expected.imag)
625
+ assert_array_almost_equal(xp.real(H), xp.real(expected))
626
+ assert_array_almost_equal(xp.imag(H), xp.imag(expected))
529
627
 
530
- def test_freq_range(self):
628
+ @skip_xp_backends("jax.numpy", reason="eigvals not available on CUDA")
629
+ def test_freq_range(self, xp):
531
630
  # Test that freqresp() finds a reasonable frequency range.
532
631
  # 1st order low-pass filter: H(s) = 1 / (s + 1)
533
632
  # Expected range is from 0.01 to 10.
534
- num = [1]
535
- den = [1, 1]
633
+ num = xp.asarray([1.])
634
+ den = xp.asarray([1, 1.])
536
635
  n = 10
537
- expected_w = np.logspace(-2, 1, n)
636
+ expected_w = _logspace(-2, 1, n, xp=xp)
538
637
  w, H = freqs(num, den, worN=n)
539
638
  assert_array_almost_equal(w, expected_w)
540
639
 
541
- def test_plot(self):
640
+ def test_plot(self, xp):
542
641
 
543
642
  def plot(w, h):
544
- assert_array_almost_equal(h, np.ones(8))
643
+ assert_array_almost_equal(h, xp.ones(8))
545
644
 
546
- assert_raises(ZeroDivisionError, freqs, [1.0], [1.0], worN=8,
547
- plot=lambda w, h: 1 / 0)
548
- freqs([1.0], [1.0], worN=8, plot=plot)
645
+ with assert_raises(ZeroDivisionError):
646
+ freqs([1.0], [1.0], worN=8, plot=lambda w, h: 1 / 0)
549
647
 
550
- def test_backward_compat(self):
648
+ freqs(xp.asarray([1.0]), xp.asarray([1.0]), worN=8, plot=plot)
649
+
650
+ def test_backward_compat(self, xp):
551
651
  # For backward compatibility, test if None act as a wrapper for default
552
- w1, h1 = freqs([1.0], [1.0])
553
- w2, h2 = freqs([1.0], [1.0], None)
652
+ w1, h1 = freqs(xp.asarray([1.0]), xp.asarray([1.0]))
653
+ w2, h2 = freqs(xp.asarray([1.0]), xp.asarray([1.0]), None)
554
654
  assert_array_almost_equal(w1, w2)
555
655
  assert_array_almost_equal(h1, h2)
556
656
 
@@ -571,47 +671,55 @@ class TestFreqs:
571
671
 
572
672
  class TestFreqs_zpk:
573
673
 
574
- def test_basic(self):
575
- _, h = freqs_zpk([1.0], [1.0], [1.0], worN=8)
576
- assert_array_almost_equal(h, np.ones(8))
674
+ def test_basic(self, xp):
675
+ _, h = freqs_zpk(
676
+ xp.asarray([1.0]), xp.asarray([1.0]), xp.asarray([1.0]), worN=8
677
+ )
678
+ assert_array_almost_equal(h, xp.ones(8))
577
679
 
578
- def test_output(self):
680
+ def test_output(self, xp):
579
681
  # 1st order low-pass filter: H(s) = 1 / (s + 1)
580
- w = [0.1, 1, 10, 100]
581
- z = []
582
- p = [-1]
682
+ w = xp.asarray([0.1, 1, 10, 100])
683
+ z = xp.asarray([])
684
+ p = xp.asarray([-1.0])
583
685
  k = 1
584
686
  w, H = freqs_zpk(z, p, k, worN=w)
585
687
  s = w * 1j
586
688
  expected = 1 / (s + 1)
587
- assert_array_almost_equal(H.real, expected.real)
588
- assert_array_almost_equal(H.imag, expected.imag)
689
+ assert_array_almost_equal(xp.real(H), xp.real(expected))
690
+ assert_array_almost_equal(xp.imag(H), xp.imag(expected))
589
691
 
590
- def test_freq_range(self):
692
+ def test_freq_range(self, xp):
591
693
  # Test that freqresp() finds a reasonable frequency range.
592
694
  # 1st order low-pass filter: H(s) = 1 / (s + 1)
593
695
  # Expected range is from 0.01 to 10.
594
- z = []
595
- p = [-1]
696
+ z = xp.asarray([])
697
+ p = xp.asarray([-1.])
596
698
  k = 1
597
699
  n = 10
598
- expected_w = np.logspace(-2, 1, n)
700
+ expected_w = _logspace(-2, 1, n, xp=xp)
599
701
  w, H = freqs_zpk(z, p, k, worN=n)
600
702
  assert_array_almost_equal(w, expected_w)
601
703
 
602
- def test_vs_freqs(self):
704
+ @skip_xp_backends("jax.numpy", reason="eigvals not available on CUDA")
705
+ def test_vs_freqs(self, xp):
603
706
  b, a = cheby1(4, 5, 100, analog=True, output='ba')
604
707
  z, p, k = cheby1(4, 5, 100, analog=True, output='zpk')
605
708
 
709
+ b, a = map(xp.asarray, (b, a)) # XXX convert cheby1
710
+ z, p = map(xp.asarray, (z, p))
711
+
606
712
  w1, h1 = freqs(b, a)
607
713
  w2, h2 = freqs_zpk(z, p, k)
608
714
  xp_assert_close(w1, w2)
609
715
  xp_assert_close(h1, h2, rtol=1e-6)
610
716
 
611
- def test_backward_compat(self):
717
+ def test_backward_compat(self, xp):
612
718
  # For backward compatibility, test if None act as a wrapper for default
613
- w1, h1 = freqs_zpk([1.0], [1.0], [1.0])
614
- w2, h2 = freqs_zpk([1.0], [1.0], [1.0], None)
719
+ # Also, keep testing `k` a length-one list: it is documented as a scalar,
720
+ # but the implementation was allowing for a one-element array-likes
721
+ w1, h1 = freqs_zpk(xp.asarray([1.0]), xp.asarray([1.0]), [1.0])
722
+ w2, h2 = freqs_zpk(xp.asarray([1.0]), xp.asarray([1.0]), [1.0], None)
615
723
  assert_array_almost_equal(w1, w2)
616
724
  assert_array_almost_equal(h1, h2)
617
725
 
@@ -632,97 +740,129 @@ class TestFreqs_zpk:
632
740
 
633
741
  class TestFreqz:
634
742
 
635
- def test_ticket1441(self):
743
+ def test_ticket1441(self, xp):
636
744
  """Regression test for ticket 1441."""
637
745
  # Because freqz previously used arange instead of linspace,
638
746
  # when N was large, it would return one more point than
639
747
  # requested.
640
748
  N = 100000
641
- w, h = freqz([1.0], worN=N)
749
+ w, h = freqz(xp.asarray([1.0]), worN=N)
642
750
  assert w.shape == (N,)
643
751
 
644
- def test_basic(self):
645
- w, h = freqz([1.0], worN=8)
646
- assert_array_almost_equal(w, np.pi * np.arange(8) / 8.)
647
- assert_array_almost_equal(h, np.ones(8))
648
- w, h = freqz([1.0], worN=9)
649
- assert_array_almost_equal(w, np.pi * np.arange(9) / 9.)
650
- assert_array_almost_equal(h, np.ones(9))
651
-
652
- for a in [1, np.ones(2)]:
653
- w, h = freqz(np.ones(2), a, worN=0)
752
+ def test_gh_22886(self, xp):
753
+ w, h = freqz(xp.asarray([1.]), worN=xp.asarray([0., 0.1]))
754
+ xp_assert_equal(w, xp.asarray([0. , 0.1]))
755
+ xp_assert_equal(h, xp.asarray([1.+0.j, 1.+0.j]))
756
+
757
+ def test_basic(self, xp):
758
+ w, h = freqz(xp.asarray([1.0]), worN=8)
759
+ assert_array_almost_equal(w, xp.pi * xp.arange(8, dtype=w.dtype) / 8.)
760
+ assert_array_almost_equal(h, xp.ones(8))
761
+ w, h = freqz(xp.asarray([1.0]), worN=9)
762
+ assert_array_almost_equal(w, xp.pi * xp.arange(9, dtype=w.dtype) / 9.)
763
+ assert_array_almost_equal(h, xp.ones(9))
764
+
765
+ for a in [1, xp.ones(2)]:
766
+ w, h = freqz(xp.ones(2), a, worN=0)
654
767
  assert w.shape == (0,)
655
768
  assert h.shape == (0,)
656
- assert h.dtype == np.dtype('complex128')
769
+ hdt = xp.complex128 if xp_default_dtype(xp) == xp.float64 else xp.complex64
770
+ assert h.dtype == hdt
657
771
 
658
- t = np.linspace(0, 1, 4, endpoint=False)
772
+ def test_basic2(self, xp):
773
+ t = xp.linspace(0, 1, 4, endpoint=False)
659
774
  for b, a, h_whole in zip(
660
- ([1., 0, 0, 0], np.sin(2 * np.pi * t)),
661
- ([1., 0, 0, 0], [0.5, 0, 0, 0]),
662
- ([1., 1., 1., 1.], [0, -4j, 0, 4j])):
775
+ (xp.asarray([1., 0, 0, 0]), xp.sin(2 * xp.pi * t)),
776
+ (xp.asarray([1., 0, 0, 0]), xp.asarray([0.5, 0, 0, 0])),
777
+ (xp.asarray([1., 1., 1., 1.]), xp.asarray([0, -4j, 0, 4j]))
778
+ ):
779
+
663
780
  w, h = freqz(b, a, worN=4, whole=True)
664
- expected_w = np.linspace(0, 2 * np.pi, 4, endpoint=False)
781
+ expected_w = xp.linspace(0, 2 * xp.pi, 4, endpoint=False)
665
782
  assert_array_almost_equal(w, expected_w)
666
783
  assert_array_almost_equal(h, h_whole)
784
+
667
785
  # simultaneously check int-like support
668
786
  w, h = freqz(b, a, worN=np.int32(4), whole=True)
669
787
  assert_array_almost_equal(w, expected_w)
670
788
  assert_array_almost_equal(h, h_whole)
789
+
671
790
  w, h = freqz(b, a, worN=w, whole=True)
672
791
  assert_array_almost_equal(w, expected_w)
673
792
  assert_array_almost_equal(h, h_whole)
674
793
 
675
- def test_basic_whole(self):
676
- w, h = freqz([1.0], worN=8, whole=True)
677
- assert_array_almost_equal(w, 2 * np.pi * np.arange(8.0) / 8)
678
- assert_array_almost_equal(h, np.ones(8))
794
+ def test_basic3(self):
795
+ t = np.linspace(0, 1, 4, endpoint=False)
796
+ expected_w = np.linspace(0, 2 * np.pi, 4, endpoint=False)
797
+ for b, a, h_whole in zip(
798
+ (np.asarray([1., 0, 0, 0]), np.sin(2 * np.pi * t)),
799
+ (np.asarray([1., 0, 0, 0]), np.asarray([0.5, 0, 0, 0])),
800
+ (np.asarray([1., 1., 1., 1.]), np.asarray([0, -4j, 0, 4j]))
801
+ ):
679
802
 
680
- def test_plot(self):
803
+ w, h = freqz(b, a, worN=np.int32(4), whole=True)
804
+ assert_array_almost_equal(w, expected_w)
805
+ assert_array_almost_equal(h, h_whole)
806
+
807
+ w, h = freqz(b, a, worN=w, whole=True)
808
+ assert_array_almost_equal(w, expected_w)
809
+ assert_array_almost_equal(h, h_whole)
810
+
811
+ def test_basic_whole(self, xp):
812
+ w, h = freqz(xp.asarray([1.0]), worN=8, whole=True)
813
+ assert_array_almost_equal(w, 2 * xp.pi * xp.arange(8.0) / 8)
814
+ assert_array_almost_equal(h, xp.ones(8))
815
+
816
+ def test_plot(self, xp):
681
817
 
682
818
  def plot(w, h):
683
- assert_array_almost_equal(w, np.pi * np.arange(8.0) / 8)
684
- assert_array_almost_equal(h, np.ones(8))
819
+ assert_array_almost_equal(w, xp.pi * xp.arange(8.0) / 8)
820
+ assert_array_almost_equal(h, xp.ones(8))
685
821
 
686
- assert_raises(ZeroDivisionError, freqz, [1.0], worN=8,
687
- plot=lambda w, h: 1 / 0)
688
- freqz([1.0], worN=8, plot=plot)
822
+ with assert_raises(ZeroDivisionError):
823
+ freqz(xp.asarray([1.0]), worN=8, plot=lambda w, h: 1 / 0)
689
824
 
690
- def test_fft_wrapping(self):
825
+ freqz(xp.asarray([1.0]), worN=8, plot=plot)
826
+
827
+ def test_fft_wrapping(self, xp):
691
828
  # Some simple real FIR filters
692
829
  bs = list() # filters
693
830
  as_ = list()
694
831
  hs_whole = list()
695
832
  hs_half = list()
696
833
  # 3 taps
697
- t = np.linspace(0, 1, 3, endpoint=False)
698
- bs.append(np.sin(2 * np.pi * t))
834
+ t = xp.linspace(0, 1, 3, endpoint=False)
835
+ bs.append(xp.sin(2 * xp.pi * t))
699
836
  as_.append(3.)
700
- hs_whole.append([0, -0.5j, 0.5j])
701
- hs_half.append([0, np.sqrt(1./12.), -0.5j])
837
+ hs_whole.append(xp.asarray([0, -0.5j, 0.5j]))
838
+ hs_half.append(xp.asarray([0, math.sqrt(1./12.), -0.5j]))
702
839
  # 4 taps
703
- t = np.linspace(0, 1, 4, endpoint=False)
704
- bs.append(np.sin(2 * np.pi * t))
840
+ t = xp.linspace(0, 1, 4, endpoint=False)
841
+ bs.append(xp.sin(2 * xp.pi * t))
705
842
  as_.append(0.5)
706
- hs_whole.append([0, -4j, 0, 4j])
707
- hs_half.append([0, np.sqrt(8), -4j, -np.sqrt(8)])
843
+ hs_whole.append(xp.asarray([0, -4j, 0, 4j]))
844
+ hs_half.append(xp.asarray([0, math.sqrt(8), -4j, -math.sqrt(8)]))
708
845
  del t
709
846
  for ii, b in enumerate(bs):
710
847
  # whole
711
848
  a = as_[ii]
712
- expected_w = np.linspace(0, 2 * np.pi, len(b), endpoint=False)
849
+ expected_w = xp.linspace(0, 2 * xp.pi, b.shape[0], endpoint=False)
713
850
  w, h = freqz(b, a, worN=expected_w, whole=True) # polyval
714
851
  err_msg = f'b = {b}, a={a}'
715
852
  assert_array_almost_equal(w, expected_w, err_msg=err_msg)
716
853
  assert_array_almost_equal(h, hs_whole[ii], err_msg=err_msg)
717
- w, h = freqz(b, a, worN=len(b), whole=True) # FFT
854
+
855
+ w, h = freqz(b, a, worN=b.shape[0], whole=True) # FFT
718
856
  assert_array_almost_equal(w, expected_w, err_msg=err_msg)
719
857
  assert_array_almost_equal(h, hs_whole[ii], err_msg=err_msg)
858
+
720
859
  # non-whole
721
- expected_w = np.linspace(0, np.pi, len(b), endpoint=False)
860
+ expected_w = xp.linspace(0, xp.pi, b.shape[0], endpoint=False)
722
861
  w, h = freqz(b, a, worN=expected_w, whole=False) # polyval
723
862
  assert_array_almost_equal(w, expected_w, err_msg=err_msg)
724
863
  assert_array_almost_equal(h, hs_half[ii], err_msg=err_msg)
725
- w, h = freqz(b, a, worN=len(b), whole=False) # FFT
864
+
865
+ w, h = freqz(b, a, worN=b.shape[0], whole=False) # FFT
726
866
  assert_array_almost_equal(w, expected_w, err_msg=err_msg)
727
867
  assert_array_almost_equal(h, hs_half[ii], err_msg=err_msg)
728
868
 
@@ -730,91 +870,100 @@ class TestFreqz:
730
870
  # assume polyval is accurate
731
871
  rng = np.random.RandomState(0)
732
872
  for ii in range(2, 10): # number of taps
733
- b = rng.randn(ii)
873
+ b = xp.asarray(rng.randn(ii))
734
874
  for kk in range(2):
735
- a = rng.randn(1) if kk == 0 else rng.randn(3)
875
+ a = xp.asarray(rng.randn(1) if kk == 0 else rng.randn(3))
736
876
  for jj in range(2):
737
877
  if jj == 1:
738
- b = b + rng.randn(ii) * 1j
878
+ b = b + xp.asarray(rng.randn(ii)) * 1j
879
+
739
880
  # whole
740
- expected_w = np.linspace(0, 2 * np.pi, ii, endpoint=False)
881
+ expected_w = xp.linspace(0, 2 * xp.pi, ii, endpoint=False)
741
882
  w, expected_h = freqz(b, a, worN=expected_w, whole=True)
742
883
  assert_array_almost_equal(w, expected_w)
743
884
  w, h = freqz(b, a, worN=ii, whole=True)
744
885
  assert_array_almost_equal(w, expected_w)
745
- assert_array_almost_equal(h, expected_h)
886
+ assert_array_almost_equal(h, expected_h, decimal=4)
887
+
746
888
  # half
747
- expected_w = np.linspace(0, np.pi, ii, endpoint=False)
889
+ expected_w = xp.linspace(0, xp.pi, ii, endpoint=False)
748
890
  w, expected_h = freqz(b, a, worN=expected_w, whole=False)
749
891
  assert_array_almost_equal(w, expected_w)
750
892
  w, h = freqz(b, a, worN=ii, whole=False)
751
893
  assert_array_almost_equal(w, expected_w)
752
- assert_array_almost_equal(h, expected_h)
894
+ assert_array_almost_equal(h, expected_h, decimal=4)
753
895
 
754
- def test_broadcasting1(self):
896
+ def test_broadcasting1(self, xp):
755
897
  # Test broadcasting with worN an integer or a 1-D array,
756
898
  # b and a are n-dimensional arrays.
757
899
  np.random.seed(123)
758
900
  b = np.random.rand(3, 5, 1)
759
901
  a = np.random.rand(2, 1)
902
+ b, a = map(xp.asarray, (b, a))
903
+
760
904
  for whole in [False, True]:
761
905
  # Test with worN being integers (one fast for FFT and one not),
762
906
  # a 1-D array, and an empty array.
763
- for worN in [16, 17, np.linspace(0, 1, 10), np.array([])]:
907
+ for worN in [16, 17, xp.linspace(0, 1, 10), xp.asarray([])]:
764
908
  w, h = freqz(b, a, worN=worN, whole=whole)
765
909
  for k in range(b.shape[1]):
766
910
  bk = b[:, k, 0]
767
911
  ak = a[:, 0]
768
912
  ww, hh = freqz(bk, ak, worN=worN, whole=whole)
769
913
  xp_assert_close(ww, w)
770
- xp_assert_close(hh, h[k])
914
+ xp_assert_close(hh, h[k, ...])
771
915
 
772
- def test_broadcasting2(self):
916
+ def test_broadcasting2(self, xp):
773
917
  # Test broadcasting with worN an integer or a 1-D array,
774
918
  # b is an n-dimensional array, and a is left at the default value.
775
919
  np.random.seed(123)
776
920
  b = np.random.rand(3, 5, 1)
921
+ b = xp.asarray(b)
777
922
  for whole in [False, True]:
778
- for worN in [16, 17, np.linspace(0, 1, 10)]:
923
+ for worN in [16, 17, xp.linspace(0, 1, 10)]:
779
924
  w, h = freqz(b, worN=worN, whole=whole)
780
925
  for k in range(b.shape[1]):
781
926
  bk = b[:, k, 0]
782
927
  ww, hh = freqz(bk, worN=worN, whole=whole)
783
928
  xp_assert_close(ww, w)
784
- xp_assert_close(hh, h[k])
929
+ xp_assert_close(hh, h[k, :])
785
930
 
786
- def test_broadcasting3(self):
931
+ def test_broadcasting3(self, xp):
787
932
  # Test broadcasting where b.shape[-1] is the same length
788
933
  # as worN, and a is left at the default value.
789
934
  np.random.seed(123)
790
935
  N = 16
791
936
  b = np.random.rand(3, N)
937
+ b = xp.asarray(b)
792
938
  for whole in [False, True]:
793
- for worN in [N, np.linspace(0, 1, N)]:
939
+ for worN in [N, xp.linspace(0, 1, N)]:
794
940
  w, h = freqz(b, worN=worN, whole=whole)
795
- assert w.size == N
941
+ assert xp_size(w) == N
796
942
  for k in range(N):
797
943
  bk = b[:, k]
798
944
  ww, hh = freqz(bk, worN=w[k], whole=whole)
799
- xp_assert_close(ww, np.asarray(w[k])[None])
800
- xp_assert_close(hh, np.asarray(h[k])[None])
945
+ xp_assert_close(ww, xp.asarray(w[k])[None])
946
+ xp_assert_close(hh, xp.asarray(h[k])[None])
801
947
 
802
- def test_broadcasting4(self):
948
+ def test_broadcasting4(self, xp):
803
949
  # Test broadcasting with worN a 2-D array.
804
950
  np.random.seed(123)
805
951
  b = np.random.rand(4, 2, 1, 1)
806
952
  a = np.random.rand(5, 2, 1, 1)
953
+ b, a = map(xp.asarray, (b, a))
954
+
807
955
  for whole in [False, True]:
808
956
  for worN in [np.random.rand(6, 7), np.empty((6, 0))]:
957
+ worN = xp.asarray(worN)
809
958
  w, h = freqz(b, a, worN=worN, whole=whole)
810
959
  xp_assert_close(w, worN, rtol=1e-14)
811
960
  assert h.shape == (2,) + worN.shape
812
961
  for k in range(2):
813
962
  ww, hh = freqz(b[:, k, 0, 0], a[:, k, 0, 0],
814
- worN=worN.ravel(),
963
+ worN=xp.reshape(worN, (-1,)),
815
964
  whole=whole)
816
- xp_assert_close(ww, worN.ravel(), rtol=1e-14)
817
- xp_assert_close(hh, h[k, :, :].ravel())
965
+ xp_assert_close(ww, xp.reshape(worN, (-1,)), rtol=1e-14)
966
+ xp_assert_close(hh, xp.reshape(h[k, :, :], (-1,)))
818
967
 
819
968
  def test_backward_compat(self):
820
969
  # For backward compatibility, test if None act as a wrapper for default
@@ -823,44 +972,44 @@ class TestFreqz:
823
972
  assert_array_almost_equal(w1, w2)
824
973
  assert_array_almost_equal(h1, h2)
825
974
 
826
- def test_fs_param(self):
975
+ def test_fs_param(self, xp):
827
976
  fs = 900
828
- b = [0.039479155677484369, 0.11843746703245311, 0.11843746703245311,
829
- 0.039479155677484369]
830
- a = [1.0, -1.3199152021838287, 0.80341991081938424,
831
- -0.16767146321568049]
977
+ b = xp.asarray([0.039479155677484369, 0.11843746703245311, 0.11843746703245311,
978
+ 0.039479155677484369])
979
+ a = xp.asarray([1.0, -1.3199152021838287, 0.80341991081938424,
980
+ -0.16767146321568049])
832
981
 
833
982
  # N = None, whole=False
834
983
  w1, h1 = freqz(b, a, fs=fs)
835
984
  w2, h2 = freqz(b, a)
836
985
  xp_assert_close(h1, h2)
837
- xp_assert_close(w1, np.linspace(0, fs/2, 512, endpoint=False))
986
+ xp_assert_close(w1, xp.linspace(0, fs/2, 512, endpoint=False))
838
987
 
839
988
  # N = None, whole=True
840
989
  w1, h1 = freqz(b, a, whole=True, fs=fs)
841
990
  w2, h2 = freqz(b, a, whole=True)
842
991
  xp_assert_close(h1, h2)
843
- xp_assert_close(w1, np.linspace(0, fs, 512, endpoint=False))
992
+ xp_assert_close(w1, xp.linspace(0, fs, 512, endpoint=False))
844
993
 
845
994
  # N = 5, whole=False
846
995
  w1, h1 = freqz(b, a, 5, fs=fs)
847
996
  w2, h2 = freqz(b, a, 5)
848
997
  xp_assert_close(h1, h2)
849
- xp_assert_close(w1, np.linspace(0, fs/2, 5, endpoint=False))
998
+ xp_assert_close(w1, xp.linspace(0, fs/2, 5, endpoint=False))
850
999
 
851
1000
  # N = 5, whole=True
852
1001
  w1, h1 = freqz(b, a, 5, whole=True, fs=fs)
853
1002
  w2, h2 = freqz(b, a, 5, whole=True)
854
1003
  xp_assert_close(h1, h2)
855
- xp_assert_close(w1, np.linspace(0, fs, 5, endpoint=False))
1004
+ xp_assert_close(w1, xp.linspace(0, fs, 5, endpoint=False))
856
1005
 
857
1006
  # w is an array_like
858
- for w in ([123], (123,), np.array([123]), (50, 123, 230),
859
- np.array([50, 123, 230])):
1007
+ for w in ([123], (123,), xp.asarray([123]), (50, 123, 230),
1008
+ xp.asarray([50, 123, 230])):
860
1009
  w1, h1 = freqz(b, a, w, fs=fs)
861
- w2, h2 = freqz(b, a, 2*pi*np.array(w)/fs)
1010
+ w2, h2 = freqz(b, a, 2*pi*xp.asarray(w, dtype=xp.float64)/ fs)
862
1011
  xp_assert_close(h1, h2)
863
- xp_assert_close(w, w1, check_dtype=False)
1012
+ xp_assert_close(w1, xp.asarray(w), check_dtype=False)
864
1013
 
865
1014
  def test_w_or_N_types(self):
866
1015
  # Measure at 7 (polyval) or 8 (fft) equally-spaced points
@@ -880,26 +1029,27 @@ class TestFreqz:
880
1029
  # Measure at frequency 8 Hz
881
1030
  for w in (8.0, 8.0+0j):
882
1031
  # Only makes sense when fs is specified
883
- w_out, h = freqz([1.0], worN=w, fs=100)
884
- assert_array_almost_equal(w_out, [8])
885
- assert_array_almost_equal(h, [1])
886
-
887
- def test_nyquist(self):
888
- w, h = freqz([1.0], worN=8, include_nyquist=True)
889
- assert_array_almost_equal(w, np.pi * np.arange(8) / 7.)
890
- assert_array_almost_equal(h, np.ones(8))
891
- w, h = freqz([1.0], worN=9, include_nyquist=True)
892
- assert_array_almost_equal(w, np.pi * np.arange(9) / 8.)
893
- assert_array_almost_equal(h, np.ones(9))
894
-
895
- for a in [1, np.ones(2)]:
896
- w, h = freqz(np.ones(2), a, worN=0, include_nyquist=True)
1032
+ w_out, h = freqz(np.asarray([1.0]), worN=w, fs=100)
1033
+ assert_array_almost_equal(w_out, np.asarray([8]))
1034
+ assert_array_almost_equal(h, np.asarray(1.), check_0d=False)
1035
+
1036
+ def test_nyquist(self, xp):
1037
+ w, h = freqz(xp.asarray([1.0]), worN=8, include_nyquist=True)
1038
+ assert_array_almost_equal(w, xp.pi * xp.arange(8, dtype=w.dtype) / 7.)
1039
+ assert_array_almost_equal(h, xp.ones(8))
1040
+ w, h = freqz(xp.asarray([1.0]), worN=9, include_nyquist=True)
1041
+ assert_array_almost_equal(w, xp.pi * xp.arange(9, dtype=w.dtype) / 8.)
1042
+ assert_array_almost_equal(h, xp.ones(9))
1043
+
1044
+ for a in [1, xp.ones(2)]:
1045
+ w, h = freqz(xp.ones(2), a, worN=0, include_nyquist=True)
897
1046
  assert w.shape == (0,)
898
1047
  assert h.shape == (0,)
899
- assert h.dtype == np.dtype('complex128')
1048
+ hdt = xp.complex128 if xp_default_dtype(xp) == xp.float64 else xp.complex64
1049
+ assert h.dtype == hdt
900
1050
 
901
- w1, h1 = freqz([1.0], worN=8, whole = True, include_nyquist=True)
902
- w2, h2 = freqz([1.0], worN=8, whole = True, include_nyquist=False)
1051
+ w1, h1 = freqz(xp.asarray([1.0]), worN=8, whole = True, include_nyquist=True)
1052
+ w2, h2 = freqz(xp.asarray([1.0]), worN=8, whole = True, include_nyquist=False)
903
1053
  assert_array_almost_equal(w1, w2)
904
1054
  assert_array_almost_equal(h1, h2)
905
1055
 
@@ -914,8 +1064,8 @@ class TestFreqz:
914
1064
  (False, True, 257),
915
1065
  (True, False, 257),
916
1066
  (True, True, 257)])
917
- def test_17289(self, whole, nyquist, worN):
918
- d = [0, 1]
1067
+ def test_17289(self, whole, nyquist, worN, xp):
1068
+ d = xp.asarray([0.0, 1.0])
919
1069
  w, Drfft = freqz(d, worN=32, whole=whole, include_nyquist=nyquist)
920
1070
  _, Dpoly = freqz(d, worN=w)
921
1071
  xp_assert_close(Drfft, Dpoly)
@@ -928,9 +1078,9 @@ class TestFreqz:
928
1078
  freqz([1.0], fs=None)
929
1079
 
930
1080
 
931
- class Testfreqz_sos:
1081
+ class TestFreqz_sos:
932
1082
 
933
- def test_freqz_sos_basic(self):
1083
+ def test_freqz_sos_basic(self, xp):
934
1084
  # Compare the results of freqz and freqz_sos for a low order
935
1085
  # Butterworth filter.
936
1086
 
@@ -938,6 +1088,8 @@ class Testfreqz_sos:
938
1088
 
939
1089
  b, a = butter(4, 0.2)
940
1090
  sos = butter(4, 0.2, output='sos')
1091
+ b, a, sos = map(xp.asarray, (b, a, sos)) # XXX until butter is converted
1092
+
941
1093
  w, h = freqz(b, a, worN=N)
942
1094
  w2, h2 = freqz_sos(sos, worN=N)
943
1095
  xp_assert_equal(w2, w)
@@ -945,132 +1097,158 @@ class Testfreqz_sos:
945
1097
 
946
1098
  b, a = ellip(3, 1, 30, (0.2, 0.3), btype='bandpass')
947
1099
  sos = ellip(3, 1, 30, (0.2, 0.3), btype='bandpass', output='sos')
1100
+ b, a, sos = map(xp.asarray, (b, a, sos)) # XXX until ellip is converted
1101
+
948
1102
  w, h = freqz(b, a, worN=N)
949
1103
  w2, h2 = freqz_sos(sos, worN=N)
950
1104
  xp_assert_equal(w2, w)
951
1105
  xp_assert_close(h2, h, rtol=1e-10, atol=1e-14)
1106
+
952
1107
  # must have at least one section
953
- assert_raises(ValueError, freqz_sos, sos[:0])
1108
+ with assert_raises(ValueError):
1109
+ freqz_sos(sos[:0, ...])
954
1110
 
955
- def test_backward_compat(self):
1111
+ def test_backward_compat(self, xp):
956
1112
  # For backward compatibility, test if None act as a wrapper for default
957
1113
  N = 500
958
1114
 
959
1115
  sos = butter(4, 0.2, output='sos')
1116
+ sos = xp.asarray(sos) # XXX until butter is converted
960
1117
  w1, h1 = freqz_sos(sos, worN=N)
961
1118
  w2, h2 = sosfreqz(sos, worN=N)
962
1119
  assert_array_almost_equal(w1, w2)
963
1120
  assert_array_almost_equal(h1, h2)
964
1121
 
965
- def test_freqz_sos_design(self):
1122
+ @skip_xp_backends("dask.array", reason="float cannot be interpreted as in integer")
1123
+ def test_freqz_sos_design(self, xp):
966
1124
  # Compare freqz_sos output against expected values for different
967
1125
  # filter types
968
1126
 
969
1127
  # from cheb2ord
970
1128
  N, Wn = cheb2ord([0.1, 0.6], [0.2, 0.5], 3, 60)
971
1129
  sos = cheby2(N, 60, Wn, 'stop', output='sos')
1130
+ sos = xp.asarray(sos) # XXX
1131
+ zero = xp.asarray(0., dtype=xp.float64)
1132
+
972
1133
  w, h = freqz_sos(sos)
973
- h = np.abs(h)
974
- w /= np.pi
975
- xp_assert_close(20 * np.log10(h[w <= 0.1]), np.asarray(0.), atol=3.01,
1134
+ h = xp.abs(h)
1135
+ w = w / xp.pi
1136
+ xp_assert_close(20 * xp.log10(h[w <= 0.1]),
1137
+ zero, atol=3.01,
976
1138
  check_shape=False)
977
- xp_assert_close(20 * np.log10(h[w >= 0.6]), np.asarray(0.), atol=3.01,
1139
+ xp_assert_close(20 * xp.log10(h[w >= 0.6]),
1140
+ zero, atol=3.01,
978
1141
  check_shape=False)
979
1142
  xp_assert_close(h[(w >= 0.2) & (w <= 0.5)],
980
- np.asarray(0.), atol=1e-3,
1143
+ zero, atol=1e-3,
981
1144
  check_shape=False) # <= -60 dB
982
1145
 
983
1146
  N, Wn = cheb2ord([0.1, 0.6], [0.2, 0.5], 3, 150)
984
1147
  sos = cheby2(N, 150, Wn, 'stop', output='sos')
1148
+ sos = xp.asarray(sos)
1149
+
985
1150
  w, h = freqz_sos(sos)
986
- dB = 20*np.log10(np.abs(h))
987
- w /= np.pi
988
- xp_assert_close(dB[w <= 0.1], np.asarray(0.0), atol=3.01, check_shape=False)
989
- xp_assert_close(dB[w >= 0.6], np.asarray(0.0), atol=3.01, check_shape=False)
990
- assert np.all(dB[(w >= 0.2) & (w <= 0.5)] < -149.9)
1151
+ dB = 20*xp.log10(xp.abs(h))
1152
+ w = w / xp.pi
1153
+ xp_assert_close(dB[w <= 0.1], zero, atol=3.01, check_shape=False)
1154
+ xp_assert_close(dB[w >= 0.6], zero, atol=3.01, check_shape=False)
1155
+ assert xp.all(dB[(w >= 0.2) & (w <= 0.5)] < -149.9)
991
1156
 
992
1157
  # from cheb1ord
993
1158
  N, Wn = cheb1ord(0.2, 0.3, 3, 40)
994
1159
  sos = cheby1(N, 3, Wn, 'low', output='sos')
1160
+ sos = xp.asarray(sos)
1161
+
995
1162
  w, h = freqz_sos(sos)
996
- h = np.abs(h)
997
- w /= np.pi
998
- xp_assert_close(20 * np.log10(h[w <= 0.2]), np.asarray(0.0), atol=3.01,
1163
+ h = xp.abs(h)
1164
+ w = w / xp.pi
1165
+ xp_assert_close(20 * xp.log10(h[w <= 0.2]), zero, atol=3.01,
999
1166
  check_shape=False)
1000
- xp_assert_close(h[w >= 0.3], np.asarray(0.0), atol=1e-2,
1167
+ xp_assert_close(h[w >= 0.3], zero, atol=1e-2,
1001
1168
  check_shape=False) # <= -40 dB
1002
1169
 
1003
1170
  N, Wn = cheb1ord(0.2, 0.3, 1, 150)
1004
1171
  sos = cheby1(N, 1, Wn, 'low', output='sos')
1172
+ sos = xp.asarray(sos)
1173
+
1005
1174
  w, h = freqz_sos(sos)
1006
- dB = 20*np.log10(np.abs(h))
1175
+ dB = 20*xp.log10(xp.abs(h))
1007
1176
  w /= np.pi
1008
- xp_assert_close(dB[w <= 0.2], np.asarray(0.0), atol=1.01,
1009
- check_shape=False)
1010
- assert np.all(dB[w >= 0.3] < -149.9)
1177
+ xp_assert_close(dB[w <= 0.2], zero, atol=1.01, check_shape=False)
1178
+ assert xp.all(dB[w >= 0.3] < -149.9)
1011
1179
 
1012
1180
  # adapted from ellipord
1013
1181
  N, Wn = ellipord(0.3, 0.2, 3, 60)
1014
1182
  sos = ellip(N, 0.3, 60, Wn, 'high', output='sos')
1183
+ sos = xp.asarray(sos)
1184
+
1015
1185
  w, h = freqz_sos(sos)
1016
- h = np.abs(h)
1017
- w /= np.pi
1018
- xp_assert_close(20 * np.log10(h[w >= 0.3]), np.asarray(0.0), atol=3.01,
1186
+ h = xp.abs(h)
1187
+ w = w / xp.pi
1188
+ xp_assert_close(20 * xp.log10(h[w >= 0.3]), zero, atol=3.01,
1019
1189
  check_shape=False)
1020
- xp_assert_close(h[w <= 0.1], np.asarray(0.0), atol=1.5e-3,
1190
+ xp_assert_close(h[w <= 0.1], zero, atol=1.5e-3,
1021
1191
  check_shape=False) # <= -60 dB (approx)
1022
1192
 
1023
1193
  # adapted from buttord
1024
1194
  N, Wn = buttord([0.2, 0.5], [0.14, 0.6], 3, 40)
1025
1195
  sos = butter(N, Wn, 'band', output='sos')
1196
+ sos = xp.asarray(sos)
1197
+
1026
1198
  w, h = freqz_sos(sos)
1027
- h = np.abs(h)
1028
- w /= np.pi
1199
+ h = xp.abs(h)
1200
+ w = w / xp.pi
1029
1201
 
1030
1202
  h014 = h[w <= 0.14]
1031
- xp_assert_close(h014, np.zeros_like(h014), atol=1e-2) # <= -40 dB
1203
+ xp_assert_close(h014, xp.zeros_like(h014), atol=1e-2) # <= -40 dB
1032
1204
  h06 = h[w >= 0.6]
1033
- xp_assert_close(h06, np.zeros_like(h06), atol=1e-2) # <= -40 dB
1034
- h0205 = 20 * np.log10(h[(w >= 0.2) & (w <= 0.5)])
1035
- xp_assert_close(h0205, np.zeros_like(h0205), atol=3.01)
1205
+ xp_assert_close(h06, xp.zeros_like(h06), atol=1e-2) # <= -40 dB
1206
+ h0205 = 20 * xp.log10(h[(w >= 0.2) & (w <= 0.5)])
1207
+ xp_assert_close(h0205, xp.zeros_like(h0205), atol=3.01)
1036
1208
 
1037
1209
  N, Wn = buttord([0.2, 0.5], [0.14, 0.6], 3, 100)
1038
1210
  sos = butter(N, Wn, 'band', output='sos')
1211
+ sos = xp.asarray(sos)
1212
+
1039
1213
  w, h = freqz_sos(sos)
1040
- dB = 20*np.log10(np.maximum(np.abs(h), 1e-10))
1041
- w /= np.pi
1214
+ dB = 20*xp.log10(xp.maximum(xp.abs(h), xp.asarray(1e-10)))
1215
+ w = w / xp.pi
1042
1216
 
1043
- assert np.all(dB[(w > 0) & (w <= 0.14)] < -99.9)
1044
- assert np.all(dB[w >= 0.6] < -99.9)
1217
+ assert xp.all(dB[(w > 0) & (w <= 0.14)] < -99.9)
1218
+ assert xp.all(dB[w >= 0.6] < -99.9)
1045
1219
  db0205 = dB[(w >= 0.2) & (w <= 0.5)]
1046
- xp_assert_close(db0205, np.zeros_like(db0205), atol=3.01)
1220
+ xp_assert_close(db0205, xp.zeros_like(db0205), atol=3.01)
1047
1221
 
1048
- def test_freqz_sos_design_ellip(self):
1222
+ def test_freqz_sos_design_ellip(self, xp):
1049
1223
  N, Wn = ellipord(0.3, 0.1, 3, 60)
1050
1224
  sos = ellip(N, 0.3, 60, Wn, 'high', output='sos')
1225
+ sos = xp.asarray(sos)
1226
+
1051
1227
  w, h = freqz_sos(sos)
1052
- h = np.abs(h)
1053
- w /= np.pi
1228
+ h = xp.abs(h)
1229
+ w = w / xp.pi
1054
1230
 
1055
- h03 = 20 * np.log10(h[w >= 0.3])
1056
- xp_assert_close(h03, np.zeros_like(h03), atol=3.01)
1231
+ h03 = 20 * xp.log10(h[w >= 0.3])
1232
+ xp_assert_close(h03, xp.zeros_like(h03), atol=3.01)
1057
1233
  h01 = h[w <= 0.1]
1058
- xp_assert_close(h01, np.zeros_like(h01), atol=1.5e-3) # <= -60 dB (approx)
1234
+ xp_assert_close(h01, xp.zeros_like(h01), atol=1.5e-3) # <= -60 dB (approx)
1059
1235
 
1060
1236
  N, Wn = ellipord(0.3, 0.2, .5, 150)
1061
1237
  sos = ellip(N, .5, 150, Wn, 'high', output='sos')
1238
+ sos = xp.asarray(sos)
1239
+
1062
1240
  w, h = freqz_sos(sos)
1063
- dB = 20*np.log10(np.maximum(np.abs(h), 1e-10))
1064
- w /= np.pi
1241
+ dB = 20*xp.log10(xp.maximum(xp.abs(h), xp.asarray(1e-10)))
1242
+ w = w / xp.pi
1065
1243
 
1066
1244
  db03 = dB[w >= 0.3]
1067
- xp_assert_close(db03, np.zeros_like(db03), atol=.55)
1245
+ xp_assert_close(db03, xp.zeros_like(db03), atol=.55)
1068
1246
  # Allow some numerical slop in the upper bound -150, so this is
1069
1247
  # a check that dB[w <= 0.2] is less than or almost equal to -150.
1070
- assert dB[w <= 0.2].max() < -150*(1 - 1e-12)
1248
+ assert xp.max(dB[w <= 0.2]) < -150*(1 - 1e-12)
1071
1249
 
1072
1250
  @mpmath_check("0.10")
1073
- def test_freqz_sos_against_mp(self):
1251
+ def test_freqz_sos_against_mp(self, xp):
1074
1252
  # Compare the result of freqz_sos applied to a high order Butterworth
1075
1253
  # filter against the result computed using mpmath. (signal.freqz fails
1076
1254
  # miserably with such high order filters.)
@@ -1081,49 +1259,63 @@ class Testfreqz_sos:
1081
1259
  with mpmath.workdps(80):
1082
1260
  z_mp, p_mp, k_mp = mpsig.butter_lp(order, Wn)
1083
1261
  w_mp, h_mp = mpsig.zpkfreqz(z_mp, p_mp, k_mp, N)
1084
- w_mp = np.array([float(x) for x in w_mp])
1085
- h_mp = np.array([complex(x) for x in h_mp])
1262
+ w_mp = xp.asarray([float(x) for x in w_mp], dtype=xp.float64)
1263
+ h_mp = xp.asarray([complex(x) for x in h_mp], dtype=xp.complex128)
1086
1264
 
1087
1265
  sos = butter(order, Wn, output='sos')
1266
+ sos = xp.asarray(sos, dtype=xp.float64)
1088
1267
  w, h = freqz_sos(sos, worN=N)
1089
1268
  xp_assert_close(w, w_mp, rtol=1e-12, atol=1e-14)
1090
1269
  xp_assert_close(h, h_mp, rtol=1e-12, atol=1e-14)
1091
1270
 
1092
- def test_fs_param(self):
1271
+ def test_fs_param(self, xp):
1093
1272
  fs = 900
1094
- sos = [[0.03934683014103762, 0.07869366028207524, 0.03934683014103762,
1273
+ sos = xp.asarray(
1274
+ [[0.03934683014103762, 0.07869366028207524, 0.03934683014103762,
1095
1275
  1.0, -0.37256600288916636, 0.0],
1096
1276
  [1.0, 1.0, 0.0, 1.0, -0.9495739996946778, 0.45125966317124144]]
1277
+ )
1097
1278
 
1098
1279
  # N = None, whole=False
1099
1280
  w1, h1 = freqz_sos(sos, fs=fs)
1100
1281
  w2, h2 = freqz_sos(sos)
1101
1282
  xp_assert_close(h1, h2)
1102
- xp_assert_close(w1, np.linspace(0, fs/2, 512, endpoint=False))
1283
+ xp_assert_close(w1, xp.linspace(0, fs/2, 512, endpoint=False))
1103
1284
 
1104
1285
  # N = None, whole=True
1105
1286
  w1, h1 = freqz_sos(sos, whole=True, fs=fs)
1106
1287
  w2, h2 = freqz_sos(sos, whole=True)
1107
1288
  xp_assert_close(h1, h2, atol=1e-27)
1108
- xp_assert_close(w1, np.linspace(0, fs, 512, endpoint=False))
1289
+ xp_assert_close(w1, xp.linspace(0, fs, 512, endpoint=False))
1109
1290
 
1110
1291
  # N = 5, whole=False
1111
1292
  w1, h1 = freqz_sos(sos, 5, fs=fs)
1112
1293
  w2, h2 = freqz_sos(sos, 5)
1113
1294
  xp_assert_close(h1, h2)
1114
- xp_assert_close(w1, np.linspace(0, fs/2, 5, endpoint=False))
1295
+ xp_assert_close(w1, xp.linspace(0, fs/2, 5, endpoint=False))
1115
1296
 
1116
1297
  # N = 5, whole=True
1117
1298
  w1, h1 = freqz_sos(sos, 5, whole=True, fs=fs)
1118
1299
  w2, h2 = freqz_sos(sos, 5, whole=True)
1119
1300
  xp_assert_close(h1, h2)
1120
- xp_assert_close(w1, np.linspace(0, fs, 5, endpoint=False))
1301
+ xp_assert_close(w1, xp.linspace(0, fs, 5, endpoint=False))
1302
+
1303
+ @skip_xp_backends(np_only=True, reason="array-likes")
1304
+ def test_fs_param2(self, xp):
1305
+ fs = 900
1306
+ sos = xp.asarray(
1307
+ [[0.03934683014103762, 0.07869366028207524, 0.03934683014103762,
1308
+ 1.0, -0.37256600288916636, 0.0],
1309
+ [1.0, 1.0, 0.0, 1.0, -0.9495739996946778, 0.45125966317124144]]
1310
+ )
1121
1311
 
1122
1312
  # w is an array_like
1123
- for w in ([123], (123,), np.array([123]), (50, 123, 230),
1124
- np.array([50, 123, 230])):
1313
+ for w in ([123], (123,), xp.asarray([123]), (50, 123, 230),
1314
+ xp.asarray([50, 123, 230])):
1125
1315
  w1, h1 = freqz_sos(sos, w, fs=fs)
1126
- w2, h2 = freqz_sos(sos, 2*pi*np.array(w)/fs)
1316
+ w1, h1 = map(xp.asarray, (w1, h1))
1317
+
1318
+ w2, h2 = freqz_sos(sos, 2*pi*xp.asarray(w, dtype=sos.dtype)/fs)
1127
1319
  xp_assert_close(h1, h2)
1128
1320
  xp_assert_close(w, w1, check_dtype=False)
1129
1321
 
@@ -1157,77 +1349,94 @@ class Testfreqz_sos:
1157
1349
 
1158
1350
  class TestFreqz_zpk:
1159
1351
 
1160
- def test_ticket1441(self):
1352
+ def test_ticket1441(self, xp):
1161
1353
  """Regression test for ticket 1441."""
1162
1354
  # Because freqz previously used arange instead of linspace,
1163
1355
  # when N was large, it would return one more point than
1164
1356
  # requested.
1165
1357
  N = 100000
1166
- w, h = freqz_zpk([0.5], [0.5], 1.0, worN=N)
1358
+ w, h = freqz_zpk(xp.asarray([0.5]), xp.asarray([0.5]), 1.0, worN=N)
1167
1359
  assert w.shape == (N,)
1168
1360
 
1169
- def test_basic(self):
1170
- w, h = freqz_zpk([0.5], [0.5], 1.0, worN=8)
1171
- assert_array_almost_equal(w, np.pi * np.arange(8.0) / 8)
1172
- assert_array_almost_equal(h, np.ones(8))
1361
+ def test_basic(self, xp):
1362
+ w, h = freqz_zpk(xp.asarray([0.5]), xp.asarray([0.5]), 1.0, worN=8)
1363
+ assert_array_almost_equal(w, xp.pi * xp.arange(8.0) / 8)
1364
+ assert_array_almost_equal(h, xp.ones(8))
1173
1365
 
1174
- def test_basic_whole(self):
1175
- w, h = freqz_zpk([0.5], [0.5], 1.0, worN=8, whole=True)
1176
- assert_array_almost_equal(w, 2 * np.pi * np.arange(8.0) / 8)
1177
- assert_array_almost_equal(h, np.ones(8))
1366
+ def test_basic_whole(self, xp):
1367
+ w, h = freqz_zpk(xp.asarray([0.5]), xp.asarray([0.5]), 1.0, worN=8, whole=True)
1368
+ assert_array_almost_equal(w, 2 * xp.pi * xp.arange(8.0) / 8)
1369
+ assert_array_almost_equal(h, xp.ones(8))
1178
1370
 
1179
- def test_vs_freqz(self):
1371
+ def test_vs_freqz(self, xp):
1180
1372
  b, a = cheby1(4, 5, 0.5, analog=False, output='ba')
1181
1373
  z, p, k = cheby1(4, 5, 0.5, analog=False, output='zpk')
1182
1374
 
1375
+ b, a = map(xp.asarray, (b, a)) # XXX convert cheby1
1376
+ z, p = map(xp.asarray, (z, p))
1377
+
1183
1378
  w1, h1 = freqz(b, a)
1184
1379
  w2, h2 = freqz_zpk(z, p, k)
1185
1380
  xp_assert_close(w1, w2)
1186
1381
  xp_assert_close(h1, h2, rtol=1e-6)
1187
1382
 
1188
- def test_backward_compat(self):
1383
+ def test_backward_compat(self, xp):
1189
1384
  # For backward compatibility, test if None act as a wrapper for default
1190
- w1, h1 = freqz_zpk([0.5], [0.5], 1.0)
1191
- w2, h2 = freqz_zpk([0.5], [0.5], 1.0, None)
1385
+ w1, h1 = freqz_zpk(xp.asarray([0.5]), xp.asarray([0.5]), 1.0)
1386
+ w2, h2 = freqz_zpk(xp.asarray([0.5]), xp.asarray([0.5]), 1.0, None)
1192
1387
  assert_array_almost_equal(w1, w2)
1193
1388
  assert_array_almost_equal(h1, h2)
1194
1389
 
1195
- def test_fs_param(self):
1390
+ def test_fs_param(self, xp):
1196
1391
  fs = 900
1197
- z = [-1, -1, -1]
1198
- p = [0.4747869998473389+0.4752230717749344j, 0.37256600288916636,
1199
- 0.4747869998473389-0.4752230717749344j]
1392
+ z = xp.asarray([-1, -1, -1.0])
1393
+ p = xp.asarray(
1394
+ [0.4747869998473389 + 0.4752230717749344j,
1395
+ 0.37256600288916636,
1396
+ 0.4747869998473389 - 0.4752230717749344j]
1397
+ )
1200
1398
  k = 0.03934683014103762
1201
1399
 
1202
1400
  # N = None, whole=False
1203
1401
  w1, h1 = freqz_zpk(z, p, k, whole=False, fs=fs)
1204
1402
  w2, h2 = freqz_zpk(z, p, k, whole=False)
1205
1403
  xp_assert_close(h1, h2)
1206
- xp_assert_close(w1, np.linspace(0, fs/2, 512, endpoint=False))
1404
+ xp_assert_close(w1, xp.linspace(0, fs/2, 512, endpoint=False))
1207
1405
 
1208
1406
  # N = None, whole=True
1209
1407
  w1, h1 = freqz_zpk(z, p, k, whole=True, fs=fs)
1210
1408
  w2, h2 = freqz_zpk(z, p, k, whole=True)
1211
1409
  xp_assert_close(h1, h2)
1212
- xp_assert_close(w1, np.linspace(0, fs, 512, endpoint=False))
1410
+ xp_assert_close(w1, xp.linspace(0, fs, 512, endpoint=False))
1213
1411
 
1214
1412
  # N = 5, whole=False
1215
1413
  w1, h1 = freqz_zpk(z, p, k, 5, fs=fs)
1216
1414
  w2, h2 = freqz_zpk(z, p, k, 5)
1217
1415
  xp_assert_close(h1, h2)
1218
- xp_assert_close(w1, np.linspace(0, fs/2, 5, endpoint=False))
1416
+ xp_assert_close(w1, xp.linspace(0, fs/2, 5, endpoint=False))
1219
1417
 
1220
1418
  # N = 5, whole=True
1221
1419
  w1, h1 = freqz_zpk(z, p, k, 5, whole=True, fs=fs)
1222
1420
  w2, h2 = freqz_zpk(z, p, k, 5, whole=True)
1223
1421
  xp_assert_close(h1, h2)
1224
- xp_assert_close(w1, np.linspace(0, fs, 5, endpoint=False))
1422
+ xp_assert_close(w1, xp.linspace(0, fs, 5, endpoint=False))
1423
+
1424
+ @skip_xp_backends(np_only=True, reason="array_likes")
1425
+ def test_fs_param2(self, xp):
1426
+ fs = 900
1427
+ z = xp.asarray([-1, -1, -1.0])
1428
+ p = xp.asarray(
1429
+ [0.4747869998473389 + 0.4752230717749344j,
1430
+ 0.37256600288916636,
1431
+ 0.4747869998473389 - 0.4752230717749344j]
1432
+ )
1433
+ k = 0.03934683014103762
1225
1434
 
1226
1435
  # w is an array_like
1227
- for w in ([123], (123,), np.array([123]), (50, 123, 230),
1228
- np.array([50, 123, 230])):
1436
+ for w in ([123], (123,), xp.asarray([123]), (50, 123, 230),
1437
+ xp.asarray([50, 123, 230])):
1229
1438
  w1, h1 = freqz_zpk(z, p, k, w, fs=fs)
1230
- w2, h2 = freqz_zpk(z, p, k, 2*pi*np.array(w)/fs)
1439
+ w2, h2 = freqz_zpk(z, p, k, 2*pi*xp.asarray(w)/fs)
1231
1440
  xp_assert_close(h1, h2)
1232
1441
  xp_assert_close(w, w1, check_dtype=False)
1233
1442
 
@@ -1253,7 +1462,7 @@ class TestFreqz_zpk:
1253
1462
 
1254
1463
  def test_fs_validation(self):
1255
1464
  with pytest.raises(ValueError, match="Sampling.*single scalar"):
1256
- freqz_zpk([1.0], [1.0], [1.0], fs=np.array([10, 20]))
1465
+ freqz_zpk([1.0], [1.0], [1.0], fs=np.array([10., 20]))
1257
1466
 
1258
1467
  with pytest.raises(ValueError, match="Sampling.*be none."):
1259
1468
  freqz_zpk([1.0], [1.0], [1.0], fs=None)
@@ -1320,62 +1529,134 @@ class TestNormalize:
1320
1529
 
1321
1530
  class TestLp2lp:
1322
1531
 
1323
- def test_basic(self):
1324
- b = [1]
1325
- a = [1, np.sqrt(2), 1]
1532
+ def test_basic(self, xp):
1533
+ b = xp.asarray([1])
1534
+ a = xp.asarray([1, math.sqrt(2), 1])
1326
1535
  b_lp, a_lp = lp2lp(b, a, 0.38574256627112119)
1327
- assert_array_almost_equal(b_lp, [0.1488], decimal=4)
1328
- assert_array_almost_equal(a_lp, [1, 0.5455, 0.1488], decimal=4)
1536
+ assert_array_almost_equal(b_lp, xp.asarray([0.1488]), decimal=4)
1537
+ assert_array_almost_equal(a_lp, xp.asarray([1, 0.5455, 0.1488]), decimal=4)
1329
1538
 
1330
1539
 
1331
1540
  class TestLp2hp:
1332
1541
 
1333
- def test_basic(self):
1334
- b = [0.25059432325190018]
1335
- a = [1, 0.59724041654134863, 0.92834805757524175, 0.25059432325190018]
1336
- b_hp, a_hp = lp2hp(b, a, 2*np.pi*5000)
1337
- xp_assert_close(b_hp, [1.0, 0, 0, 0])
1338
- xp_assert_close(a_hp, [1, 1.1638e5, 2.3522e9, 1.2373e14], rtol=1e-4)
1542
+ @skip_xp_backends(eager_only=True, reason="in-place item assignment")
1543
+ def test_basic(self, xp):
1544
+ b = xp.asarray([0.25059432325190018])
1545
+ a = xp.asarray(
1546
+ [1, 0.59724041654134863, 0.92834805757524175, 0.25059432325190018]
1547
+ )
1548
+ b_hp, a_hp = lp2hp(b, a, 2*math.pi*5000)
1549
+ xp_assert_close(b_hp, xp.asarray([1.0, 0, 0, 0]))
1550
+ xp_assert_close(
1551
+ a_hp, xp.asarray([1, 1.1638e5, 2.3522e9, 1.2373e14]), rtol=1e-4
1552
+ )
1339
1553
 
1340
1554
 
1341
1555
  class TestLp2bp:
1342
1556
 
1343
- def test_basic(self):
1344
- b = [1]
1345
- a = [1, 2, 2, 1]
1346
- b_bp, a_bp = lp2bp(b, a, 2*np.pi*4000, 2*np.pi*2000)
1347
- xp_assert_close(b_bp, [1.9844e12, 0, 0, 0], rtol=1e-6)
1348
- xp_assert_close(a_bp, [1, 2.5133e4, 2.2108e9, 3.3735e13,
1349
- 1.3965e18, 1.0028e22, 2.5202e26], rtol=1e-4)
1557
+ @skip_xp_backends(eager_only=True, reason="in-place item assignment")
1558
+ def test_basic(self, xp):
1559
+ b = xp.asarray([1])
1560
+ a = xp.asarray([1, 2, 2, 1])
1561
+ b_bp, a_bp = lp2bp(b, a, 2*math.pi*4000, 2*math.pi*2000)
1562
+ xp_assert_close(b_bp, xp.asarray([1.9844e12, 0, 0, 0]), rtol=1e-6)
1563
+ xp_assert_close(
1564
+ a_bp,
1565
+ xp.asarray([1, 2.5133e4, 2.2108e9, 3.3735e13,
1566
+ 1.3965e18, 1.0028e22, 2.5202e26]), rtol=1e-4
1567
+ )
1350
1568
 
1351
1569
 
1352
1570
  class TestLp2bs:
1353
1571
 
1354
- def test_basic(self):
1355
- b = [1]
1356
- a = [1, 1]
1572
+ @skip_xp_backends(eager_only=True, reason="in-place item assignment")
1573
+ def test_basic(self, xp):
1574
+ b = xp.asarray([1])
1575
+ a = xp.asarray([1, 1])
1357
1576
  b_bs, a_bs = lp2bs(b, a, 0.41722257286366754, 0.18460575326152251)
1358
- assert_array_almost_equal(b_bs, [1, 0, 0.17407], decimal=5)
1359
- assert_array_almost_equal(a_bs, [1, 0.18461, 0.17407], decimal=5)
1577
+ assert_array_almost_equal(b_bs, xp.asarray([1, 0, 0.17407]), decimal=5)
1578
+ assert_array_almost_equal(a_bs, xp.asarray([1, 0.18461, 0.17407]), decimal=5)
1360
1579
 
1361
1580
 
1362
1581
  class TestBilinear:
1582
+ """Tests for function `signal.bilinear`. """
1583
+
1584
+ def test_exceptions(self):
1585
+ """Raise all exceptions in `bilinear()`. """
1586
+ with pytest.raises(ValueError, match="Parameter a is not .*"):
1587
+ bilinear(1., np.array([[1, 2, 3]]))
1588
+ with pytest.raises(ValueError, match="Parameter b is not .*"):
1589
+ bilinear(np.ones((2,3)), 1. )
1363
1590
 
1364
1591
  def test_basic(self):
1592
+ # reference output values computed with sympy
1365
1593
  b = [0.14879732743343033]
1366
1594
  a = [1, 0.54552236880522209, 0.14879732743343033]
1595
+ b_zref = [0.08782128175913713, 0.17564256351827426, 0.08782128175913713]
1596
+ a_zref = [1.0, -1.0047722097030667, 0.3560573367396151]
1597
+
1367
1598
  b_z, a_z = bilinear(b, a, 0.5)
1368
- assert_array_almost_equal(b_z, [0.087821, 0.17564, 0.087821],
1369
- decimal=5)
1370
- assert_array_almost_equal(a_z, [1, -1.0048, 0.35606], decimal=4)
1599
+
1600
+ assert_array_almost_equal_nulp(b_z, b_zref)
1601
+ assert_array_almost_equal_nulp(a_z, a_zref)
1371
1602
 
1372
1603
  b = [1, 0, 0.17407467530697837]
1373
1604
  a = [1, 0.18460575326152251, 0.17407467530697837]
1605
+ b_zref = [0.8641286432189045, -1.2157757001964216, 0.8641286432189045]
1606
+ a_zref = [1.0, -1.2157757001964216, 0.7282572864378091]
1607
+
1374
1608
  b_z, a_z = bilinear(b, a, 0.5)
1375
- assert_array_almost_equal(b_z, [0.86413, -1.2158, 0.86413],
1376
- decimal=4)
1377
- assert_array_almost_equal(a_z, [1, -1.2158, 0.72826],
1378
- decimal=4)
1609
+
1610
+ assert_array_almost_equal_nulp(b_z, b_zref)
1611
+ assert_array_almost_equal_nulp(a_z, a_zref)
1612
+
1613
+
1614
+ def test_ignore_leading_zeros(self):
1615
+ # regression for gh-6606
1616
+ # results shouldn't change when leading zeros are added to
1617
+ # input numerator or denominator
1618
+ b = [0.14879732743343033]
1619
+ a = [1, 0.54552236880522209, 0.14879732743343033]
1620
+
1621
+ b_zref = [0.08782128175913713, 0.17564256351827426, 0.08782128175913713]
1622
+ a_zref = [1.0, -1.0047722097030667, 0.3560573367396151]
1623
+
1624
+ for lzn, lzd in product(range(4), range(4)):
1625
+ b_z, a_z = bilinear(np.pad(b, (lzn, 0)),
1626
+ np.pad(a, (lzd, 0)),
1627
+ 0.5)
1628
+ assert_array_almost_equal_nulp(b_z, b_zref)
1629
+ assert_array_almost_equal_nulp(a_z, a_zref)
1630
+
1631
+
1632
+ def test_complex(self):
1633
+ # reference output values computed with sympy
1634
+ # this is an elliptical filter, 5Hz width, centered at +50Hz:
1635
+ # z, p, k = signal.ellip(2, 0.5, 20, 2*np.pi*5/2, output='zpk', analog=True)
1636
+ # z = z.astype(complex) + 2j * np.pi * 50
1637
+ # p = p.astype(complex) + 2j * np.pi * 50
1638
+ # b, a = signal.zpk2tf(z, p, k)
1639
+ b = [(0.09999999999999991+0j),
1640
+ -62.831853071795805j,
1641
+ (-9505.857007071314+0j)]
1642
+ a = [(1+0j),
1643
+ (21.09511000343942-628.3185307179587j),
1644
+ (-98310.74322875646-6627.2242613473845j)]
1645
+ # sample frequency
1646
+ fs = 1000
1647
+ b_zref = [(0.09905575106715676-0.00013441423112828688j),
1648
+ (-0.18834281923181084-0.06032810039049478j),
1649
+ (0.08054306669414343+0.05766172295523972j)]
1650
+ a_zref = [(1+0j),
1651
+ (-1.8839476369292854-0.606808151331815j),
1652
+ (0.7954687330018285+0.5717459398142481j)]
1653
+
1654
+ b_z, a_z = bilinear(b, a, fs)
1655
+
1656
+ # the 3 ulp difference determined from testing
1657
+ assert_array_almost_equal_nulp(b_z, b_zref, 3)
1658
+ assert_array_almost_equal_nulp(a_z, a_zref, 3)
1659
+
1379
1660
 
1380
1661
  def test_fs_validation(self):
1381
1662
  b = [0.14879732743343033]
@@ -1389,23 +1670,30 @@ class TestBilinear:
1389
1670
 
1390
1671
  class TestLp2lp_zpk:
1391
1672
 
1392
- def test_basic(self):
1393
- z = []
1394
- p = [(-1+1j)/np.sqrt(2), (-1-1j)/np.sqrt(2)]
1673
+ @xfail_xp_backends(
1674
+ 'dask.array', reason='https://github.com/dask/dask/issues/11883'
1675
+ )
1676
+ def test_basic(self, xp):
1677
+ z = xp.asarray([])
1678
+ p = xp.asarray([(-1+1j) / math.sqrt(2), (-1-1j) / math.sqrt(2)])
1395
1679
  k = 1
1396
1680
  z_lp, p_lp, k_lp = lp2lp_zpk(z, p, k, 5)
1397
- xp_assert_equal(z_lp, [])
1398
- xp_assert_close(sort(p_lp), sort(p)*5)
1399
- xp_assert_close(k_lp, 25.)
1681
+ xp_assert_equal(z_lp, xp.asarray([]))
1682
+ xp_assert_close(_sort_cmplx(p_lp, xp=xp), _sort_cmplx(p, xp=xp) * 5)
1683
+ assert k_lp == 25.
1400
1684
 
1401
1685
  # Pseudo-Chebyshev with both poles and zeros
1402
- z = [-2j, +2j]
1403
- p = [-0.75, -0.5-0.5j, -0.5+0.5j]
1686
+ z = xp.asarray([-2j, +2j])
1687
+ p = xp.asarray([-0.75, -0.5-0.5j, -0.5+0.5j])
1404
1688
  k = 3
1405
1689
  z_lp, p_lp, k_lp = lp2lp_zpk(z, p, k, 20)
1406
- xp_assert_close(sort(z_lp), sort([-40j, +40j]))
1407
- xp_assert_close(sort(p_lp), sort([-15, -10-10j, -10+10j]))
1408
- xp_assert_close(k_lp, 60.)
1690
+ xp_assert_close(
1691
+ _sort_cmplx(z_lp, xp=xp), _sort_cmplx([-40j, +40j], xp=xp)
1692
+ )
1693
+ xp_assert_close(
1694
+ _sort_cmplx(p_lp, xp=xp), _sort_cmplx([-15, -10-10j, -10+10j], xp=xp)
1695
+ )
1696
+ assert k_lp == 60.
1409
1697
 
1410
1698
  def test_fs_validation(self):
1411
1699
  z = [-2j, +2j]
@@ -1421,80 +1709,115 @@ class TestLp2lp_zpk:
1421
1709
 
1422
1710
  class TestLp2hp_zpk:
1423
1711
 
1424
- def test_basic(self):
1425
- z = []
1426
- p = [(-1+1j)/np.sqrt(2), (-1-1j)/np.sqrt(2)]
1712
+ @xfail_xp_backends(
1713
+ 'dask.array', reason='https://github.com/dask/dask/issues/11883'
1714
+ )
1715
+ def test_basic(self, xp):
1716
+ z = xp.asarray([])
1717
+ p = xp.asarray([(-1+1j) / math.sqrt(2), (-1-1j) / math.sqrt(2)])
1427
1718
  k = 1
1428
1719
 
1429
1720
  z_hp, p_hp, k_hp = lp2hp_zpk(z, p, k, 5)
1430
- xp_assert_equal(z_hp, np.asarray([0.0, 0.0]))
1431
- xp_assert_close(sort(p_hp), sort(p)*5)
1432
- xp_assert_close(k_hp, 1.0)
1721
+ xp_assert_equal(z_hp, xp.asarray([0.0, 0.0], dtype=z_hp.dtype))
1722
+ xp_assert_close(_sort_cmplx(p_hp, xp=xp), _sort_cmplx(p, xp=xp) * 5)
1723
+ assert math.isclose(k_hp, 1.0, rel_tol=4e-7)
1433
1724
 
1434
- z = [-2j, +2j]
1435
- p = [-0.75, -0.5-0.5j, -0.5+0.5j]
1725
+ z = xp.asarray([-2j, +2j])
1726
+ p = xp.asarray([-0.75, -0.5-0.5j, -0.5+0.5j])
1436
1727
  k = 3
1437
1728
  z_hp, p_hp, k_hp = lp2hp_zpk(z, p, k, 6)
1438
- xp_assert_close(sort(z_hp), sort([-3j, 0, +3j]))
1439
- xp_assert_close(sort(p_hp), sort([-8, -6-6j, -6+6j]))
1440
- xp_assert_close(k_hp, 32.0)
1729
+ xp_assert_close(
1730
+ _sort_cmplx(z_hp, xp=xp), _sort_cmplx([-3j, 0, +3j], xp=xp)
1731
+ )
1732
+ xp_assert_close(
1733
+ _sort_cmplx(p_hp, xp=xp), _sort_cmplx([-8, -6-6j, -6+6j], xp=xp)
1734
+ )
1735
+ assert k_hp == 32.0
1441
1736
 
1442
1737
 
1443
1738
  class TestLp2bp_zpk:
1444
1739
 
1445
- def test_basic(self):
1446
- z = [-2j, +2j]
1447
- p = [-0.75, -0.5-0.5j, -0.5+0.5j]
1740
+ @xfail_xp_backends(
1741
+ 'dask.array', reason='https://github.com/dask/dask/issues/11883'
1742
+ )
1743
+ def test_basic(self, xp):
1744
+ z = xp.asarray([-2j, +2j])
1745
+ p = xp.asarray([-0.75, -0.5-0.5j, -0.5+0.5j])
1448
1746
  k = 3
1449
1747
  z_bp, p_bp, k_bp = lp2bp_zpk(z, p, k, 15, 8)
1450
- xp_assert_close(sort(z_bp), sort([-25j, -9j, 0, +9j, +25j]))
1451
- xp_assert_close(sort(p_bp), sort([-3 + 6j*sqrt(6),
1452
- -3 - 6j*sqrt(6),
1453
- +2j+sqrt(-8j-225)-2,
1454
- -2j+sqrt(+8j-225)-2,
1455
- +2j-sqrt(-8j-225)-2,
1456
- -2j-sqrt(+8j-225)-2, ]))
1457
- xp_assert_close(k_bp, 24.0)
1748
+ xp_assert_close(
1749
+ _sort_cmplx(z_bp, xp=xp),
1750
+ _sort_cmplx([-25j, -9j, 0, +9j, +25j], xp=xp), check_dtype=False
1751
+ )
1752
+ xp_assert_close(
1753
+ _sort_cmplx(p_bp, xp=xp),
1754
+ _sort_cmplx(
1755
+ [-3 + 6j*math.sqrt(6), -3 - 6j*math.sqrt(6),
1756
+ +2j + cmath.sqrt(-8j - 225) - 2, -2j + cmath.sqrt(+8j - 225) - 2,
1757
+ +2j - cmath.sqrt(-8j - 225) - 2, -2j - cmath.sqrt(+8j - 225) - 2
1758
+ ], xp=xp
1759
+ ), check_dtype=False
1760
+ )
1761
+ assert math.isclose(k_bp, 24.0)
1458
1762
 
1459
1763
 
1460
1764
  class TestLp2bs_zpk:
1461
1765
 
1462
- def test_basic(self):
1463
- z = [-2j, +2j]
1464
- p = [-0.75, -0.5-0.5j, -0.5+0.5j]
1766
+ @xfail_xp_backends(
1767
+ 'dask.array', reason='https://github.com/dask/dask/issues/11883'
1768
+ )
1769
+ def test_basic(self, xp):
1770
+ z = xp.asarray([-2j, +2j])
1771
+ p = xp.asarray([-0.75, -0.5-0.5j, -0.5+0.5j])
1465
1772
  k = 3
1466
1773
 
1467
1774
  z_bs, p_bs, k_bs = lp2bs_zpk(z, p, k, 35, 12)
1468
1775
 
1469
- xp_assert_close(sort(z_bs), sort([+35j, -35j,
1470
- +3j+sqrt(1234)*1j,
1471
- -3j+sqrt(1234)*1j,
1472
- +3j-sqrt(1234)*1j,
1473
- -3j-sqrt(1234)*1j]))
1474
- xp_assert_close(sort(p_bs), sort([+3j*sqrt(129) - 8,
1475
- -3j*sqrt(129) - 8,
1476
- (-6 + 6j) - sqrt(-1225 - 72j),
1477
- (-6 - 6j) - sqrt(-1225 + 72j),
1478
- (-6 + 6j) + sqrt(-1225 - 72j),
1479
- (-6 - 6j) + sqrt(-1225 + 72j), ]))
1480
- xp_assert_close(k_bs, 32.0)
1776
+ xp_assert_close(
1777
+ _sort_cmplx(z_bs, xp=xp),
1778
+ _sort_cmplx([+35j, -35j,
1779
+ +3j + math.sqrt(1234)*1j,
1780
+ -3j + math.sqrt(1234)*1j,
1781
+ +3j - math.sqrt(1234)*1j,
1782
+ -3j - math.sqrt(1234)*1j], xp=xp), check_dtype=False
1783
+ )
1784
+ xp_assert_close(
1785
+ _sort_cmplx(p_bs, xp=xp),
1786
+ _sort_cmplx([+3j*math.sqrt(129) - 8,
1787
+ -3j*math.sqrt(129) - 8,
1788
+ (-6 + 6j) - cmath.sqrt(-1225 - 72j),
1789
+ (-6 - 6j) - cmath.sqrt(-1225 + 72j),
1790
+ (-6 + 6j) + cmath.sqrt(-1225 - 72j),
1791
+ (-6 - 6j) + cmath.sqrt(-1225 + 72j), ], xp=xp),
1792
+ check_dtype=False
1793
+ )
1794
+ assert math.isclose(k_bs, 32.0)
1481
1795
 
1482
1796
 
1483
1797
  class TestBilinear_zpk:
1484
1798
 
1485
- def test_basic(self):
1486
- z = [-2j, +2j]
1487
- p = [-0.75, -0.5-0.5j, -0.5+0.5j]
1799
+ @xfail_xp_backends(
1800
+ 'dask.array', reason='https://github.com/dask/dask/issues/11883'
1801
+ )
1802
+ def test_basic(self, xp):
1803
+ z = xp.asarray([-2j, +2j])
1804
+ p = xp.asarray([-0.75, -0.5-0.5j, -0.5+0.5j])
1488
1805
  k = 3
1489
1806
 
1490
1807
  z_d, p_d, k_d = bilinear_zpk(z, p, k, 10)
1491
1808
 
1492
- xp_assert_close(sort(z_d), sort([(20-2j)/(20+2j), (20+2j)/(20-2j),
1493
- -1]))
1494
- xp_assert_close(sort(p_d), sort([77/83,
1495
- (1j/2 + 39/2) / (41/2 - 1j/2),
1496
- (39/2 - 1j/2) / (1j/2 + 41/2), ]))
1497
- xp_assert_close(k_d, 9696/69803)
1809
+ xp_assert_close(
1810
+ _sort_cmplx(z_d, xp=xp),
1811
+ _sort_cmplx([(20-2j) / (20+2j), (20+2j) / (20-2j), -1], xp=xp)
1812
+ )
1813
+ xp_assert_close(
1814
+ _sort_cmplx(p_d, xp=xp),
1815
+ _sort_cmplx(
1816
+ [77/83, (1j/2 + 39/2) / (41/2 - 1j/2), (39/2 - 1j/2) / (1j/2 + 41/2)],
1817
+ xp=xp
1818
+ )
1819
+ )
1820
+ assert math.isclose(k_d, 9696/69803, rel_tol=4e-7)
1498
1821
 
1499
1822
 
1500
1823
  class TestPrototypeType:
@@ -4400,86 +4723,3 @@ class TestGammatone:
4400
4723
  def test_fs_validation(self):
4401
4724
  with pytest.raises(ValueError, match="Sampling.*single scalar"):
4402
4725
  gammatone(440, 'iir', fs=np.array([10, 20]))
4403
-
4404
-
4405
- class TestOrderFilter:
4406
- def test_doc_example(self):
4407
- x = np.arange(25).reshape(5, 5)
4408
- domain = np.identity(3)
4409
-
4410
- # minimum of elements 1,3,9 (zero-padded) on phone pad
4411
- # 7,5,3 on numpad
4412
- expected = np.array(
4413
- [[0., 0., 0., 0., 0.],
4414
- [0., 0., 1., 2., 0.],
4415
- [0., 5., 6., 7., 0.],
4416
- [0., 10., 11., 12., 0.],
4417
- [0., 0., 0., 0., 0.]],
4418
- )
4419
- xp_assert_close(order_filter(x, domain, 0), expected, check_dtype=False)
4420
-
4421
- # maximum of elements 1,3,9 (zero-padded) on phone pad
4422
- # 7,5,3 on numpad
4423
- expected = np.array(
4424
- [[6., 7., 8., 9., 4.],
4425
- [11., 12., 13., 14., 9.],
4426
- [16., 17., 18., 19., 14.],
4427
- [21., 22., 23., 24., 19.],
4428
- [20., 21., 22., 23., 24.]],
4429
- )
4430
- xp_assert_close(order_filter(x, domain, 2), expected, check_dtype=False)
4431
-
4432
- # and, just to complete the set, median of zero-padded elements
4433
- expected = np.array(
4434
- [[0, 1, 2, 3, 0],
4435
- [5, 6, 7, 8, 3],
4436
- [10, 11, 12, 13, 8],
4437
- [15, 16, 17, 18, 13],
4438
- [0, 15, 16, 17, 18]],
4439
- )
4440
- xp_assert_close(order_filter(x, domain, 1), expected)
4441
-
4442
- def test_medfilt_order_filter(self):
4443
- x = np.arange(25).reshape(5, 5)
4444
-
4445
- # median of zero-padded elements 1,5,9 on phone pad
4446
- # 7,5,3 on numpad
4447
- expected = np.array(
4448
- [[0, 1, 2, 3, 0],
4449
- [1, 6, 7, 8, 4],
4450
- [6, 11, 12, 13, 9],
4451
- [11, 16, 17, 18, 14],
4452
- [0, 16, 17, 18, 0]],
4453
- )
4454
- xp_assert_close(medfilt(x, 3), expected)
4455
-
4456
- xp_assert_close(
4457
- order_filter(x, np.ones((3, 3)), 4),
4458
- expected
4459
- )
4460
-
4461
- def test_order_filter_asymmetric(self):
4462
- x = np.arange(25).reshape(5, 5)
4463
- domain = np.array(
4464
- [[1, 1, 0],
4465
- [0, 1, 0],
4466
- [0, 0, 0]],
4467
- )
4468
-
4469
- expected = np.array(
4470
- [[0, 0, 0, 0, 0],
4471
- [0, 0, 1, 2, 3],
4472
- [0, 5, 6, 7, 8],
4473
- [0, 10, 11, 12, 13],
4474
- [0, 15, 16, 17, 18]]
4475
- )
4476
- xp_assert_close(order_filter(x, domain, 0), expected)
4477
-
4478
- expected = np.array(
4479
- [[0, 0, 0, 0, 0],
4480
- [0, 1, 2, 3, 4],
4481
- [5, 6, 7, 8, 9],
4482
- [10, 11, 12, 13, 14],
4483
- [15, 16, 17, 18, 19]]
4484
- )
4485
- xp_assert_close(order_filter(x, domain, 1), expected)