scipy 1.16.0__cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl → 1.16.1__cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. scipy/__config__.py +3 -3
  2. scipy/_cyutility.cpython-312-aarch64-linux-gnu.so +0 -0
  3. scipy/_lib/_util.py +7 -0
  4. scipy/cluster/_hierarchy.cpython-312-aarch64-linux-gnu.so +0 -0
  5. scipy/cluster/_optimal_leaf_ordering.cpython-312-aarch64-linux-gnu.so +0 -0
  6. scipy/cluster/_vq.cpython-312-aarch64-linux-gnu.so +0 -0
  7. scipy/fft/_pocketfft/pypocketfft.cpython-312-aarch64-linux-gnu.so +0 -0
  8. scipy/fftpack/convolve.cpython-312-aarch64-linux-gnu.so +0 -0
  9. scipy/integrate/_dop.cpython-312-aarch64-linux-gnu.so +0 -0
  10. scipy/integrate/_lsoda.cpython-312-aarch64-linux-gnu.so +0 -0
  11. scipy/integrate/_test_odeint_banded.cpython-312-aarch64-linux-gnu.so +0 -0
  12. scipy/integrate/_vode.cpython-312-aarch64-linux-gnu.so +0 -0
  13. scipy/interpolate/_dfitpack.cpython-312-aarch64-linux-gnu.so +0 -0
  14. scipy/interpolate/_rgi_cython.cpython-312-aarch64-linux-gnu.so +0 -0
  15. scipy/io/_fast_matrix_market/_fmm_core.cpython-312-aarch64-linux-gnu.so +0 -0
  16. scipy/io/_test_fortran.cpython-312-aarch64-linux-gnu.so +0 -0
  17. scipy/io/matlab/_mio5_utils.cpython-312-aarch64-linux-gnu.so +0 -0
  18. scipy/io/matlab/_mio_utils.cpython-312-aarch64-linux-gnu.so +0 -0
  19. scipy/io/matlab/tests/test_streams.py +9 -0
  20. scipy/linalg/_decomp_interpolative.cpython-312-aarch64-linux-gnu.so +0 -0
  21. scipy/linalg/_decomp_lu_cython.cpython-312-aarch64-linux-gnu.so +0 -0
  22. scipy/linalg/_decomp_update.cpython-312-aarch64-linux-gnu.so +0 -0
  23. scipy/linalg/_fblas.cpython-312-aarch64-linux-gnu.so +0 -0
  24. scipy/linalg/_flapack.cpython-312-aarch64-linux-gnu.so +0 -0
  25. scipy/linalg/_matfuncs_schur_sqrtm.cpython-312-aarch64-linux-gnu.so +0 -0
  26. scipy/linalg/tests/test_matfuncs.py +7 -0
  27. scipy/ndimage/_cytest.cpython-312-aarch64-linux-gnu.so +0 -0
  28. scipy/ndimage/_filters.py +11 -2
  29. scipy/ndimage/_ni_label.cpython-312-aarch64-linux-gnu.so +0 -0
  30. scipy/ndimage/_rank_filter_1d.cpython-312-aarch64-linux-gnu.so +0 -0
  31. scipy/ndimage/tests/test_filters.py +52 -0
  32. scipy/optimize/_bglu_dense.cpython-312-aarch64-linux-gnu.so +0 -0
  33. scipy/optimize/_highspy/_core.cpython-312-aarch64-linux-gnu.so +0 -0
  34. scipy/optimize/_highspy/_highs_options.cpython-312-aarch64-linux-gnu.so +0 -0
  35. scipy/optimize/_lsq/least_squares.py +2 -2
  36. scipy/optimize/_minimize.py +0 -1
  37. scipy/optimize/_moduleTNC.cpython-312-aarch64-linux-gnu.so +0 -0
  38. scipy/optimize/_pava_pybind.cpython-312-aarch64-linux-gnu.so +0 -0
  39. scipy/optimize/_shgo_lib/_complex.py +2 -2
  40. scipy/optimize/_trlib/_trlib.cpython-312-aarch64-linux-gnu.so +0 -0
  41. scipy/signal/_filter_design.py +13 -1
  42. scipy/signal/_fir_filter_design.py +1 -1
  43. scipy/signal/_peak_finding_utils.cpython-312-aarch64-linux-gnu.so +0 -0
  44. scipy/signal/_polyutils.py +1 -1
  45. scipy/signal/_sosfilt.cpython-312-aarch64-linux-gnu.so +0 -0
  46. scipy/signal/_upfirdn_apply.cpython-312-aarch64-linux-gnu.so +0 -0
  47. scipy/signal/tests/test_filter_design.py +19 -0
  48. scipy/signal/tests/test_fir_filter_design.py +5 -0
  49. scipy/sparse/_base.py +4 -1
  50. scipy/sparse/_csparsetools.cpython-312-aarch64-linux-gnu.so +0 -0
  51. scipy/sparse/csgraph/_flow.cpython-312-aarch64-linux-gnu.so +0 -0
  52. scipy/sparse/csgraph/_matching.cpython-312-aarch64-linux-gnu.so +0 -0
  53. scipy/sparse/csgraph/_min_spanning_tree.cpython-312-aarch64-linux-gnu.so +0 -0
  54. scipy/sparse/csgraph/_reordering.cpython-312-aarch64-linux-gnu.so +0 -0
  55. scipy/sparse/csgraph/_shortest_path.cpython-312-aarch64-linux-gnu.so +0 -0
  56. scipy/sparse/csgraph/_tools.cpython-312-aarch64-linux-gnu.so +0 -0
  57. scipy/sparse/csgraph/_traversal.cpython-312-aarch64-linux-gnu.so +0 -0
  58. scipy/sparse/linalg/_eigen/arpack/_arpack.cpython-312-aarch64-linux-gnu.so +0 -0
  59. scipy/sparse/linalg/_propack/_cpropack.cpython-312-aarch64-linux-gnu.so +0 -0
  60. scipy/sparse/linalg/_propack/_dpropack.cpython-312-aarch64-linux-gnu.so +0 -0
  61. scipy/sparse/linalg/_propack/_spropack.cpython-312-aarch64-linux-gnu.so +0 -0
  62. scipy/sparse/linalg/_propack/_zpropack.cpython-312-aarch64-linux-gnu.so +0 -0
  63. scipy/sparse/tests/test_base.py +3 -0
  64. scipy/spatial/_ckdtree.cpython-312-aarch64-linux-gnu.so +0 -0
  65. scipy/spatial/_distance_pybind.cpython-312-aarch64-linux-gnu.so +0 -0
  66. scipy/spatial/_hausdorff.cpython-312-aarch64-linux-gnu.so +0 -0
  67. scipy/spatial/_qhull.cpython-312-aarch64-linux-gnu.so +0 -0
  68. scipy/spatial/_voronoi.cpython-312-aarch64-linux-gnu.so +0 -0
  69. scipy/spatial/transform/_rigid_transform.cpython-312-aarch64-linux-gnu.so +0 -0
  70. scipy/spatial/transform/_rotation.cpython-312-aarch64-linux-gnu.so +0 -0
  71. scipy/special/_ellip_harm_2.cpython-312-aarch64-linux-gnu.so +0 -0
  72. scipy/special/_specfun.cpython-312-aarch64-linux-gnu.so +0 -0
  73. scipy/special/_ufuncs.cpython-312-aarch64-linux-gnu.so +0 -0
  74. scipy/special/_ufuncs_cxx.cpython-312-aarch64-linux-gnu.so +0 -0
  75. scipy/stats/_ansari_swilk_statistics.cpython-312-aarch64-linux-gnu.so +0 -0
  76. scipy/stats/_biasedurn.cpython-312-aarch64-linux-gnu.so +0 -0
  77. scipy/stats/_continuous_distns.py +19 -16
  78. scipy/stats/_qmc_cy.cpython-312-aarch64-linux-gnu.so +0 -0
  79. scipy/stats/_rcont/rcont.cpython-312-aarch64-linux-gnu.so +0 -0
  80. scipy/stats/_sobol.cpython-312-aarch64-linux-gnu.so +0 -0
  81. scipy/stats/_stats.cpython-312-aarch64-linux-gnu.so +0 -0
  82. scipy/stats/_unuran/unuran_wrapper.cpython-312-aarch64-linux-gnu.so +0 -0
  83. scipy/stats/tests/test_distributions.py +13 -0
  84. scipy/stats/tests/test_fast_gen_inversion.py +2 -0
  85. scipy/version.py +2 -2
  86. {scipy-1.16.0.dist-info → scipy-1.16.1.dist-info}/METADATA +2 -1
  87. {scipy-1.16.0.dist-info → scipy-1.16.1.dist-info}/RECORD +89 -89
  88. {scipy-1.16.0.dist-info → scipy-1.16.1.dist-info}/LICENSE.txt +0 -0
  89. {scipy-1.16.0.dist-info → scipy-1.16.1.dist-info}/WHEEL +0 -0
scipy/__config__.py CHANGED
@@ -59,7 +59,7 @@ CONFIG = _cleanup(
59
59
  },
60
60
  "pythran": {
61
61
  "version": r"0.18.0",
62
- "include directory": r"../../tmp/build-env-kgwue17m/lib/python3.12/site-packages/pythran"
62
+ "include directory": r"../../tmp/build-env-1147qsel/lib/python3.12/site-packages/pythran"
63
63
  },
64
64
  },
65
65
  "Machine Information": {
@@ -100,13 +100,13 @@ CONFIG = _cleanup(
100
100
  },
101
101
  "pybind11": {
102
102
  "name": "pybind11",
103
- "version": "2.13.6",
103
+ "version": "3.0.0",
104
104
  "detection method": "config-tool",
105
105
  "include directory": r"unknown",
106
106
  },
107
107
  },
108
108
  "Python Information": {
109
- "path": r"/tmp/build-env-kgwue17m/bin/python",
109
+ "path": r"/tmp/build-env-1147qsel/bin/python",
110
110
  "version": "3.12",
111
111
  },
112
112
  }
scipy/_lib/_util.py CHANGED
@@ -351,6 +351,13 @@ def _transition_to_rng(old_name, *, position_num=None, end_version=None,
351
351
 
352
352
  return fun(*args, **kwargs)
353
353
 
354
+ # Add the old parameter name to the function signature
355
+ wrapped_signature = inspect.signature(fun)
356
+ wrapper.__signature__ = wrapped_signature.replace(parameters=[
357
+ *wrapped_signature.parameters.values(),
358
+ inspect.Parameter(old_name, inspect.Parameter.KEYWORD_ONLY, default=None),
359
+ ])
360
+
354
361
  if replace_doc:
355
362
  doc = FunctionDoc(wrapper)
356
363
  parameter_names = [param.name for param in doc['Parameters']]
@@ -2,7 +2,9 @@
2
2
 
3
3
  """
4
4
 
5
+ import platform
5
6
  import os
7
+ import sys
6
8
  import zlib
7
9
 
8
10
  from io import BytesIO
@@ -15,6 +17,7 @@ import numpy as np
15
17
 
16
18
  from numpy.testing import assert_, assert_equal
17
19
  from pytest import raises as assert_raises
20
+ import pytest
18
21
 
19
22
  from scipy.io.matlab._streams import (make_stream,
20
23
  GenericStream, ZlibInputStream,
@@ -194,6 +197,9 @@ class TestZlibInputStream:
194
197
  stream.seek(1024)
195
198
  assert_(stream.all_data_read())
196
199
 
200
+ @pytest.mark.skipif(
201
+ (platform.system() == 'Windows' and sys.version_info >= (3, 14)),
202
+ reason='gh-23185')
197
203
  def test_all_data_read_overlap(self):
198
204
  COMPRESSION_LEVEL = 6
199
205
 
@@ -210,6 +216,9 @@ class TestZlibInputStream:
210
216
  stream.seek(len(data))
211
217
  assert_(stream.all_data_read())
212
218
 
219
+ @pytest.mark.skipif(
220
+ (platform.system() == 'Windows' and sys.version_info >= (3, 14)),
221
+ reason='gh-23185')
213
222
  def test_all_data_read_bad_checksum(self):
214
223
  COMPRESSION_LEVEL = 6
215
224
 
@@ -460,6 +460,13 @@ class TestSqrtM:
460
460
  np.fill_diagonal(M, 1)
461
461
  assert np.isrealobj(sqrtm(M))
462
462
 
463
+ def test_gh23278(self):
464
+ M = np.array([[1., 0., 0.], [0, 1, -1j], [0, 1j, 2]])
465
+ sq = sqrtm(M)
466
+ assert_allclose(sq @ sq, M, atol=1e-14)
467
+ sq = sqrtm(M.astype(np.complex64))
468
+ assert_allclose(sq @ sq, M, atol=1e-6)
469
+
463
470
  def test_data_size_preservation_uint_in_float_out(self):
464
471
  M = np.eye(10, dtype=np.uint8)
465
472
  assert sqrtm(M).dtype == np.float64
scipy/ndimage/_filters.py CHANGED
@@ -232,7 +232,9 @@ def vectorized_filter(input, function, *, size=None, footprint=None, output=None
232
232
  We adjust `size` to the number of dimensions indicated by `axes`.
233
233
  For instance, if `axes` is ``(0, 2, 1)`` and ``n`` is passed for ``size``,
234
234
  then the effective `size` is ``(n, n, n)``.
235
- %(output)s
235
+ output : array, optional
236
+ The array in which to place the output. By default, an array of the dtype
237
+ returned by `function` will be created.
236
238
  mode : {'reflect', 'constant', 'nearest', 'mirror', 'wrap'}, optional
237
239
  The `mode` parameter determines how the input array is extended
238
240
  beyond its boundaries. Default is 'reflect'. Behavior for each valid
@@ -1987,7 +1989,14 @@ def _rank_filter(input, rank, size=None, footprint=None, output=None,
1987
1989
  "A sequence of modes is not supported by non-separable rank "
1988
1990
  "filters")
1989
1991
  mode = _ni_support._extend_mode_to_code(mode, is_filter=True)
1990
- if input.ndim == 1:
1992
+ # Some corner cases are currently not allowed to use the
1993
+ # "new"/fast 1D rank filter code, including when the
1994
+ # footprint is large compared to the array size.
1995
+ # See discussion in gh-23293; longer-term it may be possible
1996
+ # to allow the fast path for these corner cases as well,
1997
+ # if algorithmic fixes are found.
1998
+ lim2 = input.size - ((footprint.size - 1) // 2 - origin)
1999
+ if input.ndim == 1 and ((lim2 >= 0) or (input.size == 1)):
1991
2000
  if input.dtype in (np.int64, np.float64, np.float32):
1992
2001
  x = input
1993
2002
  x_out = output
@@ -3029,3 +3029,55 @@ class TestVectorizedFilter:
3029
3029
  def test_gh_22586_crash_property(x, size, mode):
3030
3030
  # property-based test for median_filter resilience to hard crashing
3031
3031
  ndimage.median_filter(x, size=size, mode=mode)
3032
+
3033
+
3034
+ @pytest.mark.parametrize('samples, mode, size, expected', [
3035
+ ([1, 2], "reflect", 5, [2, 1]),
3036
+ ([2], "reflect", 5, [2]), # original failure from gh-23075
3037
+ ([2], "nearest", 5, [2]),
3038
+ ([2], "wrap", 5, [2]),
3039
+ ([2], "mirror", 5, [2]),
3040
+ ([2], "constant", 5, [0]),
3041
+ ([2], "reflect", 1, [2]),
3042
+ ([2], "nearest", 1, [2]),
3043
+ ([2], "wrap", 1, [2]),
3044
+ ([2], "mirror", 1, [2]),
3045
+ ([2], "constant", 1, [2]),
3046
+ ([2], "reflect", 100, [2]),
3047
+ ([2], "nearest", 100, [2]),
3048
+ ([2], "wrap", 100, [2]),
3049
+ ([2], "mirror", 100, [2]),
3050
+ ([2], "constant", 100, [0]),
3051
+ ])
3052
+ def test_gh_23075(samples, mode, size, expected):
3053
+ # results verified against SciPy 1.14.1, before the median_filter
3054
+ # overhaul
3055
+ sample_array = np.asarray(samples, dtype=np.float32)
3056
+ expected = np.asarray(expected, dtype=np.float32)
3057
+ filtered_samples = ndimage.median_filter(sample_array, size=size, mode=mode)
3058
+ xp_assert_close(filtered_samples, expected, check_shape=True, check_dtype=True)
3059
+
3060
+
3061
+ @pytest.mark.parametrize('samples, size, cval, expected', [
3062
+ ([2], 5, 17.7, [17.7]),
3063
+ ([2], 1, 0, [2]),
3064
+ ([2], 100, 1.4, [1.4]),
3065
+ ([9], 137, -7807.7, [-7807.7]),
3066
+ ])
3067
+ def test_gh_23075_constant(samples, size, cval, expected):
3068
+ # results verified against SciPy 1.14.1, before the median_filter
3069
+ # overhaul
3070
+ sample_array = np.asarray(samples, dtype=np.single)
3071
+ expected = np.asarray(expected, dtype=np.single)
3072
+ filtered_samples = ndimage.median_filter(sample_array,
3073
+ size=size,
3074
+ mode="constant",
3075
+ cval=cval)
3076
+ xp_assert_close(filtered_samples, expected, check_shape=True, check_dtype=True)
3077
+
3078
+
3079
+ def test_median_filter_lim2():
3080
+ sample_array = np.ones(8)
3081
+ expected = np.ones(8)
3082
+ filtered_samples = ndimage.median_filter(sample_array, size=19, mode="reflect")
3083
+ xp_assert_close(filtered_samples, expected, check_shape=True, check_dtype=True)
@@ -17,7 +17,7 @@ from .trf import trf
17
17
  from .dogbox import dogbox
18
18
  from .common import EPS, in_bounds, make_strictly_feasible
19
19
 
20
-
20
+
21
21
  from scipy.optimize._optimize import _wrap_callback
22
22
 
23
23
  TERMINATION_MESSAGES = {
@@ -392,7 +392,7 @@ def least_squares(
392
392
 
393
393
  * For 'trf' : ``x_scale == 1``
394
394
  * For 'dogbox' : ``x_scale == 1``
395
- * For 'jac' : ``x_scale == 'jac'``
395
+ * For 'lm' : ``x_scale == 'jac'``
396
396
 
397
397
  .. versionchanged:: 1.16.0
398
398
  The default keyword value is changed from 1 to None to indicate that
@@ -188,7 +188,6 @@ def minimize(fun, x0, args=(), method=None, jac=None, hess=None,
188
188
 
189
189
  Equality constraint means that the constraint function result is to
190
190
  be zero whereas inequality means that it is to be non-negative.
191
- Note that COBYLA only supports inequality constraints.
192
191
 
193
192
  tol : float, optional
194
193
  Tolerance for termination. When `tol` is specified, the selected
@@ -183,6 +183,7 @@ class Complex:
183
183
  self.V = VertexCacheIndex()
184
184
 
185
185
  self.V_non_symm = [] # List of non-symmetric vertices
186
+ self.split_edge = cache(self._split_edge)
186
187
 
187
188
  def __call__(self):
188
189
  return self.H
@@ -995,8 +996,7 @@ class Complex:
995
996
  d_v0v1.connect(d_v1v2)
996
997
  return
997
998
 
998
- @cache
999
- def split_edge(self, v1, v2):
999
+ def _split_edge(self, v1, v2):
1000
1000
  v1 = self.V[v1]
1001
1001
  v2 = self.V[v2]
1002
1002
  # Destroy original edge, if it exists:
@@ -60,6 +60,17 @@ def _is_int_type(x):
60
60
  return True
61
61
 
62
62
 
63
+ def _real_dtype_for_complex(dtyp, *, xp):
64
+ if xp.isdtype(dtyp, 'real floating'):
65
+ return dtyp
66
+ if dtyp == xp.complex64:
67
+ return xp.float32
68
+ elif dtyp == xp.complex128:
69
+ return xp.float64
70
+ else:
71
+ raise ValueError(f"Unknown dtype {dtyp}.")
72
+
73
+
63
74
  # https://github.com/numpy/numpy/blob/v2.2.0/numpy/_core/function_base.py#L195-L302
64
75
  def _logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None, *, xp):
65
76
  if not isinstance(base, float | int) and xp.asarray(base).ndim > 0:
@@ -488,6 +499,7 @@ def freqz(b, a=1, worN=512, whole=False, plot=None, fs=2*pi,
488
499
  if xp.isdtype(a.dtype, 'integral'):
489
500
  a = xp.astype(a, xp_default_dtype(xp))
490
501
  res_dtype = xp.result_type(b, a)
502
+ real_dtype = _real_dtype_for_complex(res_dtype, xp=xp)
491
503
 
492
504
  b = xpx.atleast_nd(b, ndim=1, xp=xp)
493
505
  a = xpx.atleast_nd(a, ndim=1, xp=xp)
@@ -509,7 +521,7 @@ def freqz(b, a=1, worN=512, whole=False, plot=None, fs=2*pi,
509
521
  # if include_nyquist is true and whole is false, w should
510
522
  # include end point
511
523
  w = xp.linspace(0, lastpoint, N,
512
- endpoint=include_nyquist and not whole, dtype=res_dtype)
524
+ endpoint=include_nyquist and not whole, dtype=real_dtype)
513
525
  n_fft = N if whole else 2 * (N - 1) if include_nyquist else 2 * N
514
526
  if (xp_size(a) == 1 and (b.ndim == 1 or (b.shape[-1] == 1))
515
527
  and n_fft >= b.shape[0]
@@ -834,7 +834,7 @@ def remez(numtaps, bands, desired, *, weight=None, type='bandpass',
834
834
  xp = array_namespace(bands, desired, weight)
835
835
  bands = np.asarray(bands)
836
836
  desired = np.asarray(desired)
837
- if weight:
837
+ if weight is not None:
838
838
  weight = np.asarray(weight)
839
839
 
840
840
  fs = _validate_fs(fs, allow_none=True)
@@ -117,7 +117,7 @@ def poly(seq_of_zeros, *, xp):
117
117
  if xp.isdtype(a.dtype, 'complex floating'):
118
118
  # if complex roots are all complex conjugates, the roots are real.
119
119
  roots = xp.asarray(seq_of_zeros, dtype=xp.complex128)
120
- if xp.all(_sort_cmplx(roots, xp) == _sort_cmplx(xp.conj(roots), xp)):
120
+ if xp.all(xp.sort(xp.imag(roots)) == xp.sort(xp.imag(xp.conj(roots)))):
121
121
  a = xp.asarray(xp.real(a), copy=True)
122
122
 
123
123
  return a
@@ -382,6 +382,19 @@ class TestTf2Sos:
382
382
  sos2 = tf2sos(b, a, analog=analog)
383
383
  assert_array_almost_equal(sos, sos2, decimal=4)
384
384
 
385
+ def test_gh_23221(self):
386
+ # Tests that this tf2sos call below does not produce ComplexWarnings
387
+ # This test is specific for scipy==1.16.0: later scipy versions do not produce
388
+ # the warning.
389
+ with suppress_warnings():
390
+ warnings.simplefilter("error")
391
+ tf2sos([0.21860986786301265, -0.4372197357260253, -0.2186098678630126,
392
+ 0.8744394714520509, -0.21860986786301248, -0.4372197357260253,
393
+ 0.21860986786301265],
394
+ [1., -4.18323041786553, 6.829924151626914, -5.407777865686045,
395
+ 2.0773105450802336, -0.33482732571537893, 0.0186009178695853 ]
396
+ )
397
+
385
398
 
386
399
  @skip_xp_backends(
387
400
  cpu_only=True, reason="XXX zpk2sos is numpy-only", exceptions=['cupy']
@@ -754,6 +767,12 @@ class TestFreqz:
754
767
  xp_assert_equal(w, xp.asarray([0. , 0.1]))
755
768
  xp_assert_equal(h, xp.asarray([1.+0.j, 1.+0.j]))
756
769
 
770
+ def test_gh_23277(self):
771
+ # backwards compatibility: `w` array must be real, not complex
772
+ filt = [0.5 + 0.0j, 0.5 + 0.0j]
773
+ w, _ = freqz(filt, worN=8)
774
+ assert w.dtype == np.float64
775
+
757
776
  def test_basic(self, xp):
758
777
  w, h = freqz(xp.asarray([1.0]), worN=8)
759
778
  assert_array_almost_equal(w, xp.pi * xp.arange(8, dtype=w.dtype) / 8.)
@@ -546,6 +546,11 @@ class TestRemez:
546
546
  with pytest.raises(ValueError, match="Sampling.*single scalar"):
547
547
  remez(11, .1, 1, fs=np.array([10, 20]))
548
548
 
549
+ def test_gh_23266(self, xp):
550
+ bands = xp.asarray([0.0, 0.2, 0.3, 0.5])
551
+ desired = xp.asarray([1.0, 0.0])
552
+ weight = xp.asarray([1.0, 2.0])
553
+ remez(21, bands, desired, weight=weight)
549
554
 
550
555
 
551
556
  @skip_xp_backends(cpu_only=True, reason="lstsq")
scipy/sparse/_base.py CHANGED
@@ -494,7 +494,10 @@ class _spbase(SparseABC):
494
494
  return self._mul_scalar(other)
495
495
 
496
496
  if self.ndim < 3:
497
- return self.tocsr()._multiply_2d_with_broadcasting(other)
497
+ try:
498
+ return self._multiply_2d_with_broadcasting(other)
499
+ except AttributeError:
500
+ return self.tocsr()._multiply_2d_with_broadcasting(other)
498
501
 
499
502
  if not (issparse(other) or isdense(other)):
500
503
  # If it's a list or whatever, treat it like an array
@@ -1624,6 +1624,9 @@ class _TestCommon:
1624
1624
  B = array([[0,7,0],[0,-4,0]])
1625
1625
  Asp = self.spcreator(A)
1626
1626
  Bsp = self.spcreator(B)
1627
+ # check output format
1628
+ out_fmt = Asp.format if Asp.format in ('csc', 'dia', 'bsr') else 'csr'
1629
+ assert (Asp.multiply(Bsp)).format == out_fmt
1627
1630
  assert_almost_equal(Asp.multiply(Bsp).toarray(), A*B) # sparse/sparse
1628
1631
  assert_almost_equal(Asp.multiply(B).toarray(), A*B) # sparse/dense
1629
1632
 
@@ -935,23 +935,26 @@ class beta_gen(rv_continuous):
935
935
  log_term = sum_ab*np.log1p(a/b) + np.log(b) - 2*np.log(sum_ab)
936
936
  return t1 + t2 + log_term
937
937
 
938
- def threshold_large(v):
939
- if v == 1.0:
940
- return 1000
941
-
942
- j = np.log10(v)
943
- digits = int(j)
944
- d = int(v / 10 ** digits) + 2
945
- return d*10**(7 + j)
946
-
947
- if a >= 4.96e6 and b >= 4.96e6:
948
- return asymptotic_ab_large(a, b)
949
- elif a <= 4.9e6 and b - a >= 1e6 and b >= threshold_large(a):
950
- return asymptotic_b_large(a, b)
951
- elif b <= 4.9e6 and a - b >= 1e6 and a >= threshold_large(b):
938
+ def asymptotic_a_large(a, b):
952
939
  return asymptotic_b_large(b, a)
953
- else:
954
- return regular(a, b)
940
+
941
+ def threshold_large(v):
942
+ j = np.floor(np.log10(v))
943
+ d = np.floor(v / 10 ** j) + 2
944
+ return xpx.apply_where(v != 1.0, (d, j), lambda d_, j_: d_ * 10**(7 + j_),
945
+ fill_value=1000)
946
+
947
+ threshold_a = threshold_large(a)
948
+ threshold_b = threshold_large(b)
949
+ return _lazyselect([(a >= 4.96e6) & (b >= 4.96e6),
950
+ (a <= 4.9e6) & (b - a >= 1e6) & (b >= threshold_a),
951
+ (b <= 4.9e6) & (a - b >= 1e6) & (a >= threshold_b),
952
+ (a < 4.9e6) & (b < 4.9e6)
953
+ ],
954
+ [asymptotic_ab_large, asymptotic_b_large,
955
+ asymptotic_a_large, regular],
956
+ [a, b]
957
+ )
955
958
 
956
959
 
957
960
  beta = beta_gen(a=0.0, b=1.0, name='beta')
@@ -5003,6 +5003,19 @@ class TestBeta:
5003
5003
  # return float(entropy)
5004
5004
  assert_allclose(stats.beta(a, b).entropy(), ref, rtol=tol)
5005
5005
 
5006
+ def test_entropy_broadcasting(self):
5007
+ # gh-23127 reported that the entropy method of the beta
5008
+ # distribution did not broadcast correctly.
5009
+ Beta = stats.make_distribution(stats.beta)
5010
+ a = np.asarray([5e6, 100, 1e9, 10])
5011
+ b = np.asarray([5e6, 1e9, 100, 20])
5012
+ res = Beta(a=a, b=b).entropy()
5013
+ ref = np.asarray([Beta(a=a[0], b=b[0]).entropy(),
5014
+ Beta(a=a[1], b=b[1]).entropy(),
5015
+ Beta(a=a[2], b=b[2]).entropy(),
5016
+ Beta(a=a[3], b=b[3]).entropy()])
5017
+ assert_allclose(res, ref)
5018
+
5006
5019
 
5007
5020
  class TestBetaPrime:
5008
5021
  # the test values are used in test_cdf_gh_17631 / test_ppf_gh_17631
@@ -6,6 +6,7 @@ from numpy.testing import (assert_array_equal, assert_allclose,
6
6
  from copy import deepcopy
7
7
  from scipy.stats.sampling import FastGeneratorInversion
8
8
  from scipy import stats
9
+ from scipy._lib._testutils import IS_MUSL
9
10
 
10
11
 
11
12
  def test_bad_args():
@@ -142,6 +143,7 @@ def test_geninvgauss_uerror():
142
143
 
143
144
 
144
145
  # TODO: add more distributions
146
+ @pytest.mark.skipif(IS_MUSL, reason="Hits RecursionError, see gh-23172")
145
147
  @pytest.mark.fail_slow(5)
146
148
  @pytest.mark.parametrize(("distname, args"), [("beta", (0.11, 0.11))])
147
149
  def test_error_extreme_params(distname, args):
scipy/version.py CHANGED
@@ -2,10 +2,10 @@
2
2
  """
3
3
  Module to expose more detailed version info for the installed `scipy`
4
4
  """
5
- version = "1.16.0"
5
+ version = "1.16.1"
6
6
  full_version = version
7
7
  short_version = version.split('.dev')[0]
8
- git_revision = "4d3dcc103612a2edaec7069638b7f8d0d75cab8b"
8
+ git_revision = "0cf8e9541b1a2457992bf4ec2c0c669da373e497"
9
9
  release = 'dev' not in version and '+' not in version
10
10
 
11
11
  if not release:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: scipy
3
- Version: 1.16.0
3
+ Version: 1.16.1
4
4
  Summary: Fundamental algorithms for scientific computing in Python
5
5
  Maintainer-Email: SciPy Developers <scipy-dev@python.org>
6
6
  License: Copyright (c) 2001-2002 Enthought, Inc. 2003, SciPy Developers.
@@ -948,6 +948,7 @@ Classifier: Programming Language :: Python :: 3
948
948
  Classifier: Programming Language :: Python :: 3.11
949
949
  Classifier: Programming Language :: Python :: 3.12
950
950
  Classifier: Programming Language :: Python :: 3.13
951
+ Classifier: Programming Language :: Python :: 3.14
951
952
  Classifier: Topic :: Software Development :: Libraries
952
953
  Classifier: Topic :: Scientific/Engineering
953
954
  Classifier: Operating System :: Microsoft :: Windows