Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/scipy/linalg/_basic.py: 7%
431 statements
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-23 06:43 +0000
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-23 06:43 +0000
1#
2# Author: Pearu Peterson, March 2002
3#
4# w/ additions by Travis Oliphant, March 2002
5# and Jake Vanderplas, August 2012
7from warnings import warn
8from itertools import product
9import numpy as np
10from numpy import atleast_1d, atleast_2d
11from .lapack import get_lapack_funcs, _compute_lwork
12from ._misc import LinAlgError, _datacopied, LinAlgWarning
13from ._decomp import _asarray_validated
14from . import _decomp, _decomp_svd
15from ._solve_toeplitz import levinson
16from ._cythonized_array_utils import find_det_from_lu
17from scipy._lib.deprecation import _NoValue, _deprecate_positional_args
19# deprecated imports to be removed in SciPy 1.13.0
20from scipy.linalg._flinalg_py import get_flinalg_funcs # noqa
22__all__ = ['solve', 'solve_triangular', 'solveh_banded', 'solve_banded',
23 'solve_toeplitz', 'solve_circulant', 'inv', 'det', 'lstsq',
24 'pinv', 'pinvh', 'matrix_balance', 'matmul_toeplitz']
27# The numpy facilities for type-casting checks are too slow for small sized
28# arrays and eat away the time budget for the checkups. Here we set a
29# precomputed dict container of the numpy.can_cast() table.
31# It can be used to determine quickly what a dtype can be cast to LAPACK
32# compatible types, i.e., 'float32, float64, complex64, complex128'.
33# Then it can be checked via "casting_dict[arr.dtype.char]"
34lapack_cast_dict = {x: ''.join([y for y in 'fdFD' if np.can_cast(x, y)])
35 for x in np.typecodes['All']}
38# Linear equations
39def _solve_check(n, info, lamch=None, rcond=None):
40 """ Check arguments during the different steps of the solution phase """
41 if info < 0:
42 raise ValueError('LAPACK reported an illegal value in {}-th argument'
43 '.'.format(-info))
44 elif 0 < info:
45 raise LinAlgError('Matrix is singular.')
47 if lamch is None:
48 return
49 E = lamch('E')
50 if rcond < E:
51 warn('Ill-conditioned matrix (rcond={:.6g}): '
52 'result may not be accurate.'.format(rcond),
53 LinAlgWarning, stacklevel=3)
56def solve(a, b, lower=False, overwrite_a=False,
57 overwrite_b=False, check_finite=True, assume_a='gen',
58 transposed=False):
59 """
60 Solves the linear equation set ``a @ x == b`` for the unknown ``x``
61 for square `a` matrix.
63 If the data matrix is known to be a particular type then supplying the
64 corresponding string to ``assume_a`` key chooses the dedicated solver.
65 The available options are
67 =================== ========
68 generic matrix 'gen'
69 symmetric 'sym'
70 hermitian 'her'
71 positive definite 'pos'
72 =================== ========
74 If omitted, ``'gen'`` is the default structure.
76 The datatype of the arrays define which solver is called regardless
77 of the values. In other words, even when the complex array entries have
78 precisely zero imaginary parts, the complex solver will be called based
79 on the data type of the array.
81 Parameters
82 ----------
83 a : (N, N) array_like
84 Square input data
85 b : (N, NRHS) array_like
86 Input data for the right hand side.
87 lower : bool, default: False
88 Ignored if ``assume_a == 'gen'`` (the default). If True, the
89 calculation uses only the data in the lower triangle of `a`;
90 entries above the diagonal are ignored. If False (default), the
91 calculation uses only the data in the upper triangle of `a`; entries
92 below the diagonal are ignored.
93 overwrite_a : bool, default: False
94 Allow overwriting data in `a` (may enhance performance).
95 overwrite_b : bool, default: False
96 Allow overwriting data in `b` (may enhance performance).
97 check_finite : bool, default: True
98 Whether to check that the input matrices contain only finite numbers.
99 Disabling may give a performance gain, but may result in problems
100 (crashes, non-termination) if the inputs do contain infinities or NaNs.
101 assume_a : str, {'gen', 'sym', 'her', 'pos'}
102 Valid entries are explained above.
103 transposed : bool, default: False
104 If True, solve ``a.T @ x == b``. Raises `NotImplementedError`
105 for complex `a`.
107 Returns
108 -------
109 x : (N, NRHS) ndarray
110 The solution array.
112 Raises
113 ------
114 ValueError
115 If size mismatches detected or input a is not square.
116 LinAlgError
117 If the matrix is singular.
118 LinAlgWarning
119 If an ill-conditioned input a is detected.
120 NotImplementedError
121 If transposed is True and input a is a complex matrix.
123 Notes
124 -----
125 If the input b matrix is a 1-D array with N elements, when supplied
126 together with an NxN input a, it is assumed as a valid column vector
127 despite the apparent size mismatch. This is compatible with the
128 numpy.dot() behavior and the returned result is still 1-D array.
130 The generic, symmetric, Hermitian and positive definite solutions are
131 obtained via calling ?GESV, ?SYSV, ?HESV, and ?POSV routines of
132 LAPACK respectively.
134 Examples
135 --------
136 Given `a` and `b`, solve for `x`:
138 >>> import numpy as np
139 >>> a = np.array([[3, 2, 0], [1, -1, 0], [0, 5, 1]])
140 >>> b = np.array([2, 4, -1])
141 >>> from scipy import linalg
142 >>> x = linalg.solve(a, b)
143 >>> x
144 array([ 2., -2., 9.])
145 >>> np.dot(a, x) == b
146 array([ True, True, True], dtype=bool)
148 """
149 # Flags for 1-D or N-D right-hand side
150 b_is_1D = False
152 a1 = atleast_2d(_asarray_validated(a, check_finite=check_finite))
153 b1 = atleast_1d(_asarray_validated(b, check_finite=check_finite))
154 n = a1.shape[0]
156 overwrite_a = overwrite_a or _datacopied(a1, a)
157 overwrite_b = overwrite_b or _datacopied(b1, b)
159 if a1.shape[0] != a1.shape[1]:
160 raise ValueError('Input a needs to be a square matrix.')
162 if n != b1.shape[0]:
163 # Last chance to catch 1x1 scalar a and 1-D b arrays
164 if not (n == 1 and b1.size != 0):
165 raise ValueError('Input b has to have same number of rows as '
166 'input a')
168 # accommodate empty arrays
169 if b1.size == 0:
170 return np.asfortranarray(b1.copy())
172 # regularize 1-D b arrays to 2D
173 if b1.ndim == 1:
174 if n == 1:
175 b1 = b1[None, :]
176 else:
177 b1 = b1[:, None]
178 b_is_1D = True
180 if assume_a not in ('gen', 'sym', 'her', 'pos'):
181 raise ValueError('{} is not a recognized matrix structure'
182 ''.format(assume_a))
184 # for a real matrix, describe it as "symmetric", not "hermitian"
185 # (lapack doesn't know what to do with real hermitian matrices)
186 if assume_a == 'her' and not np.iscomplexobj(a1):
187 assume_a = 'sym'
189 # Get the correct lamch function.
190 # The LAMCH functions only exists for S and D
191 # So for complex values we have to convert to real/double.
192 if a1.dtype.char in 'fF': # single precision
193 lamch = get_lapack_funcs('lamch', dtype='f')
194 else:
195 lamch = get_lapack_funcs('lamch', dtype='d')
197 # Currently we do not have the other forms of the norm calculators
198 # lansy, lanpo, lanhe.
199 # However, in any case they only reduce computations slightly...
200 lange = get_lapack_funcs('lange', (a1,))
202 # Since the I-norm and 1-norm are the same for symmetric matrices
203 # we can collect them all in this one call
204 # Note however, that when issuing 'gen' and form!='none', then
205 # the I-norm should be used
206 if transposed:
207 trans = 1
208 norm = 'I'
209 if np.iscomplexobj(a1):
210 raise NotImplementedError('scipy.linalg.solve can currently '
211 'not solve a^T x = b or a^H x = b '
212 'for complex matrices.')
213 else:
214 trans = 0
215 norm = '1'
217 anorm = lange(norm, a1)
219 # Generalized case 'gesv'
220 if assume_a == 'gen':
221 gecon, getrf, getrs = get_lapack_funcs(('gecon', 'getrf', 'getrs'),
222 (a1, b1))
223 lu, ipvt, info = getrf(a1, overwrite_a=overwrite_a)
224 _solve_check(n, info)
225 x, info = getrs(lu, ipvt, b1,
226 trans=trans, overwrite_b=overwrite_b)
227 _solve_check(n, info)
228 rcond, info = gecon(lu, anorm, norm=norm)
229 # Hermitian case 'hesv'
230 elif assume_a == 'her':
231 hecon, hesv, hesv_lw = get_lapack_funcs(('hecon', 'hesv',
232 'hesv_lwork'), (a1, b1))
233 lwork = _compute_lwork(hesv_lw, n, lower)
234 lu, ipvt, x, info = hesv(a1, b1, lwork=lwork,
235 lower=lower,
236 overwrite_a=overwrite_a,
237 overwrite_b=overwrite_b)
238 _solve_check(n, info)
239 rcond, info = hecon(lu, ipvt, anorm)
240 # Symmetric case 'sysv'
241 elif assume_a == 'sym':
242 sycon, sysv, sysv_lw = get_lapack_funcs(('sycon', 'sysv',
243 'sysv_lwork'), (a1, b1))
244 lwork = _compute_lwork(sysv_lw, n, lower)
245 lu, ipvt, x, info = sysv(a1, b1, lwork=lwork,
246 lower=lower,
247 overwrite_a=overwrite_a,
248 overwrite_b=overwrite_b)
249 _solve_check(n, info)
250 rcond, info = sycon(lu, ipvt, anorm)
251 # Positive definite case 'posv'
252 else:
253 pocon, posv = get_lapack_funcs(('pocon', 'posv'),
254 (a1, b1))
255 lu, x, info = posv(a1, b1, lower=lower,
256 overwrite_a=overwrite_a,
257 overwrite_b=overwrite_b)
258 _solve_check(n, info)
259 rcond, info = pocon(lu, anorm)
261 _solve_check(n, info, lamch, rcond)
263 if b_is_1D:
264 x = x.ravel()
266 return x
269def solve_triangular(a, b, trans=0, lower=False, unit_diagonal=False,
270 overwrite_b=False, check_finite=True):
271 """
272 Solve the equation `a x = b` for `x`, assuming a is a triangular matrix.
274 Parameters
275 ----------
276 a : (M, M) array_like
277 A triangular matrix
278 b : (M,) or (M, N) array_like
279 Right-hand side matrix in `a x = b`
280 lower : bool, optional
281 Use only data contained in the lower triangle of `a`.
282 Default is to use upper triangle.
283 trans : {0, 1, 2, 'N', 'T', 'C'}, optional
284 Type of system to solve:
286 ======== =========
287 trans system
288 ======== =========
289 0 or 'N' a x = b
290 1 or 'T' a^T x = b
291 2 or 'C' a^H x = b
292 ======== =========
293 unit_diagonal : bool, optional
294 If True, diagonal elements of `a` are assumed to be 1 and
295 will not be referenced.
296 overwrite_b : bool, optional
297 Allow overwriting data in `b` (may enhance performance)
298 check_finite : bool, optional
299 Whether to check that the input matrices contain only finite numbers.
300 Disabling may give a performance gain, but may result in problems
301 (crashes, non-termination) if the inputs do contain infinities or NaNs.
303 Returns
304 -------
305 x : (M,) or (M, N) ndarray
306 Solution to the system `a x = b`. Shape of return matches `b`.
308 Raises
309 ------
310 LinAlgError
311 If `a` is singular
313 Notes
314 -----
315 .. versionadded:: 0.9.0
317 Examples
318 --------
319 Solve the lower triangular system a x = b, where::
321 [3 0 0 0] [4]
322 a = [2 1 0 0] b = [2]
323 [1 0 1 0] [4]
324 [1 1 1 1] [2]
326 >>> import numpy as np
327 >>> from scipy.linalg import solve_triangular
328 >>> a = np.array([[3, 0, 0, 0], [2, 1, 0, 0], [1, 0, 1, 0], [1, 1, 1, 1]])
329 >>> b = np.array([4, 2, 4, 2])
330 >>> x = solve_triangular(a, b, lower=True)
331 >>> x
332 array([ 1.33333333, -0.66666667, 2.66666667, -1.33333333])
333 >>> a.dot(x) # Check the result
334 array([ 4., 2., 4., 2.])
336 """
338 a1 = _asarray_validated(a, check_finite=check_finite)
339 b1 = _asarray_validated(b, check_finite=check_finite)
340 if len(a1.shape) != 2 or a1.shape[0] != a1.shape[1]:
341 raise ValueError('expected square matrix')
342 if a1.shape[0] != b1.shape[0]:
343 raise ValueError('shapes of a {} and b {} are incompatible'
344 .format(a1.shape, b1.shape))
345 overwrite_b = overwrite_b or _datacopied(b1, b)
347 trans = {'N': 0, 'T': 1, 'C': 2}.get(trans, trans)
348 trtrs, = get_lapack_funcs(('trtrs',), (a1, b1))
349 if a1.flags.f_contiguous or trans == 2:
350 x, info = trtrs(a1, b1, overwrite_b=overwrite_b, lower=lower,
351 trans=trans, unitdiag=unit_diagonal)
352 else:
353 # transposed system is solved since trtrs expects Fortran ordering
354 x, info = trtrs(a1.T, b1, overwrite_b=overwrite_b, lower=not lower,
355 trans=not trans, unitdiag=unit_diagonal)
357 if info == 0:
358 return x
359 if info > 0:
360 raise LinAlgError("singular matrix: resolution failed at diagonal %d" %
361 (info-1))
362 raise ValueError('illegal value in %dth argument of internal trtrs' %
363 (-info))
366def solve_banded(l_and_u, ab, b, overwrite_ab=False, overwrite_b=False,
367 check_finite=True):
368 """
369 Solve the equation a x = b for x, assuming a is banded matrix.
371 The matrix a is stored in `ab` using the matrix diagonal ordered form::
373 ab[u + i - j, j] == a[i,j]
375 Example of `ab` (shape of a is (6,6), `u` =1, `l` =2)::
377 * a01 a12 a23 a34 a45
378 a00 a11 a22 a33 a44 a55
379 a10 a21 a32 a43 a54 *
380 a20 a31 a42 a53 * *
382 Parameters
383 ----------
384 (l, u) : (integer, integer)
385 Number of non-zero lower and upper diagonals
386 ab : (`l` + `u` + 1, M) array_like
387 Banded matrix
388 b : (M,) or (M, K) array_like
389 Right-hand side
390 overwrite_ab : bool, optional
391 Discard data in `ab` (may enhance performance)
392 overwrite_b : bool, optional
393 Discard data in `b` (may enhance performance)
394 check_finite : bool, optional
395 Whether to check that the input matrices contain only finite numbers.
396 Disabling may give a performance gain, but may result in problems
397 (crashes, non-termination) if the inputs do contain infinities or NaNs.
399 Returns
400 -------
401 x : (M,) or (M, K) ndarray
402 The solution to the system a x = b. Returned shape depends on the
403 shape of `b`.
405 Examples
406 --------
407 Solve the banded system a x = b, where::
409 [5 2 -1 0 0] [0]
410 [1 4 2 -1 0] [1]
411 a = [0 1 3 2 -1] b = [2]
412 [0 0 1 2 2] [2]
413 [0 0 0 1 1] [3]
415 There is one nonzero diagonal below the main diagonal (l = 1), and
416 two above (u = 2). The diagonal banded form of the matrix is::
418 [* * -1 -1 -1]
419 ab = [* 2 2 2 2]
420 [5 4 3 2 1]
421 [1 1 1 1 *]
423 >>> import numpy as np
424 >>> from scipy.linalg import solve_banded
425 >>> ab = np.array([[0, 0, -1, -1, -1],
426 ... [0, 2, 2, 2, 2],
427 ... [5, 4, 3, 2, 1],
428 ... [1, 1, 1, 1, 0]])
429 >>> b = np.array([0, 1, 2, 2, 3])
430 >>> x = solve_banded((1, 2), ab, b)
431 >>> x
432 array([-2.37288136, 3.93220339, -4. , 4.3559322 , -1.3559322 ])
434 """
436 a1 = _asarray_validated(ab, check_finite=check_finite, as_inexact=True)
437 b1 = _asarray_validated(b, check_finite=check_finite, as_inexact=True)
438 # Validate shapes.
439 if a1.shape[-1] != b1.shape[0]:
440 raise ValueError("shapes of ab and b are not compatible.")
441 (nlower, nupper) = l_and_u
442 if nlower + nupper + 1 != a1.shape[0]:
443 raise ValueError("invalid values for the number of lower and upper "
444 "diagonals: l+u+1 (%d) does not equal ab.shape[0] "
445 "(%d)" % (nlower + nupper + 1, ab.shape[0]))
447 overwrite_b = overwrite_b or _datacopied(b1, b)
448 if a1.shape[-1] == 1:
449 b2 = np.array(b1, copy=(not overwrite_b))
450 b2 /= a1[1, 0]
451 return b2
452 if nlower == nupper == 1:
453 overwrite_ab = overwrite_ab or _datacopied(a1, ab)
454 gtsv, = get_lapack_funcs(('gtsv',), (a1, b1))
455 du = a1[0, 1:]
456 d = a1[1, :]
457 dl = a1[2, :-1]
458 du2, d, du, x, info = gtsv(dl, d, du, b1, overwrite_ab, overwrite_ab,
459 overwrite_ab, overwrite_b)
460 else:
461 gbsv, = get_lapack_funcs(('gbsv',), (a1, b1))
462 a2 = np.zeros((2*nlower + nupper + 1, a1.shape[1]), dtype=gbsv.dtype)
463 a2[nlower:, :] = a1
464 lu, piv, x, info = gbsv(nlower, nupper, a2, b1, overwrite_ab=True,
465 overwrite_b=overwrite_b)
466 if info == 0:
467 return x
468 if info > 0:
469 raise LinAlgError("singular matrix")
470 raise ValueError('illegal value in %d-th argument of internal '
471 'gbsv/gtsv' % -info)
474def solveh_banded(ab, b, overwrite_ab=False, overwrite_b=False, lower=False,
475 check_finite=True):
476 """
477 Solve equation a x = b. a is Hermitian positive-definite banded matrix.
479 Uses Thomas' Algorithm, which is more efficient than standard LU
480 factorization, but should only be used for Hermitian positive-definite
481 matrices.
483 The matrix ``a`` is stored in `ab` either in lower diagonal or upper
484 diagonal ordered form:
486 ab[u + i - j, j] == a[i,j] (if upper form; i <= j)
487 ab[ i - j, j] == a[i,j] (if lower form; i >= j)
489 Example of `ab` (shape of ``a`` is (6, 6), number of upper diagonals,
490 ``u`` =2)::
492 upper form:
493 * * a02 a13 a24 a35
494 * a01 a12 a23 a34 a45
495 a00 a11 a22 a33 a44 a55
497 lower form:
498 a00 a11 a22 a33 a44 a55
499 a10 a21 a32 a43 a54 *
500 a20 a31 a42 a53 * *
502 Cells marked with * are not used.
504 Parameters
505 ----------
506 ab : (``u`` + 1, M) array_like
507 Banded matrix
508 b : (M,) or (M, K) array_like
509 Right-hand side
510 overwrite_ab : bool, optional
511 Discard data in `ab` (may enhance performance)
512 overwrite_b : bool, optional
513 Discard data in `b` (may enhance performance)
514 lower : bool, optional
515 Is the matrix in the lower form. (Default is upper form)
516 check_finite : bool, optional
517 Whether to check that the input matrices contain only finite numbers.
518 Disabling may give a performance gain, but may result in problems
519 (crashes, non-termination) if the inputs do contain infinities or NaNs.
521 Returns
522 -------
523 x : (M,) or (M, K) ndarray
524 The solution to the system ``a x = b``. Shape of return matches shape
525 of `b`.
527 Notes
528 -----
529 In the case of a non-positive definite matrix ``a``, the solver
530 `solve_banded` may be used.
532 Examples
533 --------
534 Solve the banded system ``A x = b``, where::
536 [ 4 2 -1 0 0 0] [1]
537 [ 2 5 2 -1 0 0] [2]
538 A = [-1 2 6 2 -1 0] b = [2]
539 [ 0 -1 2 7 2 -1] [3]
540 [ 0 0 -1 2 8 2] [3]
541 [ 0 0 0 -1 2 9] [3]
543 >>> import numpy as np
544 >>> from scipy.linalg import solveh_banded
546 ``ab`` contains the main diagonal and the nonzero diagonals below the
547 main diagonal. That is, we use the lower form:
549 >>> ab = np.array([[ 4, 5, 6, 7, 8, 9],
550 ... [ 2, 2, 2, 2, 2, 0],
551 ... [-1, -1, -1, -1, 0, 0]])
552 >>> b = np.array([1, 2, 2, 3, 3, 3])
553 >>> x = solveh_banded(ab, b, lower=True)
554 >>> x
555 array([ 0.03431373, 0.45938375, 0.05602241, 0.47759104, 0.17577031,
556 0.34733894])
559 Solve the Hermitian banded system ``H x = b``, where::
561 [ 8 2-1j 0 0 ] [ 1 ]
562 H = [2+1j 5 1j 0 ] b = [1+1j]
563 [ 0 -1j 9 -2-1j] [1-2j]
564 [ 0 0 -2+1j 6 ] [ 0 ]
566 In this example, we put the upper diagonals in the array ``hb``:
568 >>> hb = np.array([[0, 2-1j, 1j, -2-1j],
569 ... [8, 5, 9, 6 ]])
570 >>> b = np.array([1, 1+1j, 1-2j, 0])
571 >>> x = solveh_banded(hb, b)
572 >>> x
573 array([ 0.07318536-0.02939412j, 0.11877624+0.17696461j,
574 0.10077984-0.23035393j, -0.00479904-0.09358128j])
576 """
577 a1 = _asarray_validated(ab, check_finite=check_finite)
578 b1 = _asarray_validated(b, check_finite=check_finite)
579 # Validate shapes.
580 if a1.shape[-1] != b1.shape[0]:
581 raise ValueError("shapes of ab and b are not compatible.")
583 overwrite_b = overwrite_b or _datacopied(b1, b)
584 overwrite_ab = overwrite_ab or _datacopied(a1, ab)
586 if a1.shape[0] == 2:
587 ptsv, = get_lapack_funcs(('ptsv',), (a1, b1))
588 if lower:
589 d = a1[0, :].real
590 e = a1[1, :-1]
591 else:
592 d = a1[1, :].real
593 e = a1[0, 1:].conj()
594 d, du, x, info = ptsv(d, e, b1, overwrite_ab, overwrite_ab,
595 overwrite_b)
596 else:
597 pbsv, = get_lapack_funcs(('pbsv',), (a1, b1))
598 c, x, info = pbsv(a1, b1, lower=lower, overwrite_ab=overwrite_ab,
599 overwrite_b=overwrite_b)
600 if info > 0:
601 raise LinAlgError("%dth leading minor not positive definite" % info)
602 if info < 0:
603 raise ValueError('illegal value in %dth argument of internal '
604 'pbsv' % -info)
605 return x
608def solve_toeplitz(c_or_cr, b, check_finite=True):
609 """Solve a Toeplitz system using Levinson Recursion
611 The Toeplitz matrix has constant diagonals, with c as its first column
612 and r as its first row. If r is not given, ``r == conjugate(c)`` is
613 assumed.
615 Parameters
616 ----------
617 c_or_cr : array_like or tuple of (array_like, array_like)
618 The vector ``c``, or a tuple of arrays (``c``, ``r``). Whatever the
619 actual shape of ``c``, it will be converted to a 1-D array. If not
620 supplied, ``r = conjugate(c)`` is assumed; in this case, if c[0] is
621 real, the Toeplitz matrix is Hermitian. r[0] is ignored; the first row
622 of the Toeplitz matrix is ``[c[0], r[1:]]``. Whatever the actual shape
623 of ``r``, it will be converted to a 1-D array.
624 b : (M,) or (M, K) array_like
625 Right-hand side in ``T x = b``.
626 check_finite : bool, optional
627 Whether to check that the input matrices contain only finite numbers.
628 Disabling may give a performance gain, but may result in problems
629 (result entirely NaNs) if the inputs do contain infinities or NaNs.
631 Returns
632 -------
633 x : (M,) or (M, K) ndarray
634 The solution to the system ``T x = b``. Shape of return matches shape
635 of `b`.
637 See Also
638 --------
639 toeplitz : Toeplitz matrix
641 Notes
642 -----
643 The solution is computed using Levinson-Durbin recursion, which is faster
644 than generic least-squares methods, but can be less numerically stable.
646 Examples
647 --------
648 Solve the Toeplitz system T x = b, where::
650 [ 1 -1 -2 -3] [1]
651 T = [ 3 1 -1 -2] b = [2]
652 [ 6 3 1 -1] [2]
653 [10 6 3 1] [5]
655 To specify the Toeplitz matrix, only the first column and the first
656 row are needed.
658 >>> import numpy as np
659 >>> c = np.array([1, 3, 6, 10]) # First column of T
660 >>> r = np.array([1, -1, -2, -3]) # First row of T
661 >>> b = np.array([1, 2, 2, 5])
663 >>> from scipy.linalg import solve_toeplitz, toeplitz
664 >>> x = solve_toeplitz((c, r), b)
665 >>> x
666 array([ 1.66666667, -1. , -2.66666667, 2.33333333])
668 Check the result by creating the full Toeplitz matrix and
669 multiplying it by `x`. We should get `b`.
671 >>> T = toeplitz(c, r)
672 >>> T.dot(x)
673 array([ 1., 2., 2., 5.])
675 """
676 # If numerical stability of this algorithm is a problem, a future
677 # developer might consider implementing other O(N^2) Toeplitz solvers,
678 # such as GKO (https://www.jstor.org/stable/2153371) or Bareiss.
680 r, c, b, dtype, b_shape = _validate_args_for_toeplitz_ops(
681 c_or_cr, b, check_finite, keep_b_shape=True)
683 # Form a 1-D array of values to be used in the matrix, containing a
684 # reversed copy of r[1:], followed by c.
685 vals = np.concatenate((r[-1:0:-1], c))
686 if b is None:
687 raise ValueError('illegal value, `b` is a required argument')
689 if b.ndim == 1:
690 x, _ = levinson(vals, np.ascontiguousarray(b))
691 else:
692 x = np.column_stack([levinson(vals, np.ascontiguousarray(b[:, i]))[0]
693 for i in range(b.shape[1])])
694 x = x.reshape(*b_shape)
696 return x
699def _get_axis_len(aname, a, axis):
700 ax = axis
701 if ax < 0:
702 ax += a.ndim
703 if 0 <= ax < a.ndim:
704 return a.shape[ax]
705 raise ValueError(f"'{aname}axis' entry is out of bounds")
708def solve_circulant(c, b, singular='raise', tol=None,
709 caxis=-1, baxis=0, outaxis=0):
710 """Solve C x = b for x, where C is a circulant matrix.
712 `C` is the circulant matrix associated with the vector `c`.
714 The system is solved by doing division in Fourier space. The
715 calculation is::
717 x = ifft(fft(b) / fft(c))
719 where `fft` and `ifft` are the fast Fourier transform and its inverse,
720 respectively. For a large vector `c`, this is *much* faster than
721 solving the system with the full circulant matrix.
723 Parameters
724 ----------
725 c : array_like
726 The coefficients of the circulant matrix.
727 b : array_like
728 Right-hand side matrix in ``a x = b``.
729 singular : str, optional
730 This argument controls how a near singular circulant matrix is
731 handled. If `singular` is "raise" and the circulant matrix is
732 near singular, a `LinAlgError` is raised. If `singular` is
733 "lstsq", the least squares solution is returned. Default is "raise".
734 tol : float, optional
735 If any eigenvalue of the circulant matrix has an absolute value
736 that is less than or equal to `tol`, the matrix is considered to be
737 near singular. If not given, `tol` is set to::
739 tol = abs_eigs.max() * abs_eigs.size * np.finfo(np.float64).eps
741 where `abs_eigs` is the array of absolute values of the eigenvalues
742 of the circulant matrix.
743 caxis : int
744 When `c` has dimension greater than 1, it is viewed as a collection
745 of circulant vectors. In this case, `caxis` is the axis of `c` that
746 holds the vectors of circulant coefficients.
747 baxis : int
748 When `b` has dimension greater than 1, it is viewed as a collection
749 of vectors. In this case, `baxis` is the axis of `b` that holds the
750 right-hand side vectors.
751 outaxis : int
752 When `c` or `b` are multidimensional, the value returned by
753 `solve_circulant` is multidimensional. In this case, `outaxis` is
754 the axis of the result that holds the solution vectors.
756 Returns
757 -------
758 x : ndarray
759 Solution to the system ``C x = b``.
761 Raises
762 ------
763 LinAlgError
764 If the circulant matrix associated with `c` is near singular.
766 See Also
767 --------
768 circulant : circulant matrix
770 Notes
771 -----
772 For a 1-D vector `c` with length `m`, and an array `b`
773 with shape ``(m, ...)``,
775 solve_circulant(c, b)
777 returns the same result as
779 solve(circulant(c), b)
781 where `solve` and `circulant` are from `scipy.linalg`.
783 .. versionadded:: 0.16.0
785 Examples
786 --------
787 >>> import numpy as np
788 >>> from scipy.linalg import solve_circulant, solve, circulant, lstsq
790 >>> c = np.array([2, 2, 4])
791 >>> b = np.array([1, 2, 3])
792 >>> solve_circulant(c, b)
793 array([ 0.75, -0.25, 0.25])
795 Compare that result to solving the system with `scipy.linalg.solve`:
797 >>> solve(circulant(c), b)
798 array([ 0.75, -0.25, 0.25])
800 A singular example:
802 >>> c = np.array([1, 1, 0, 0])
803 >>> b = np.array([1, 2, 3, 4])
805 Calling ``solve_circulant(c, b)`` will raise a `LinAlgError`. For the
806 least square solution, use the option ``singular='lstsq'``:
808 >>> solve_circulant(c, b, singular='lstsq')
809 array([ 0.25, 1.25, 2.25, 1.25])
811 Compare to `scipy.linalg.lstsq`:
813 >>> x, resid, rnk, s = lstsq(circulant(c), b)
814 >>> x
815 array([ 0.25, 1.25, 2.25, 1.25])
817 A broadcasting example:
819 Suppose we have the vectors of two circulant matrices stored in an array
820 with shape (2, 5), and three `b` vectors stored in an array with shape
821 (3, 5). For example,
823 >>> c = np.array([[1.5, 2, 3, 0, 0], [1, 1, 4, 3, 2]])
824 >>> b = np.arange(15).reshape(-1, 5)
826 We want to solve all combinations of circulant matrices and `b` vectors,
827 with the result stored in an array with shape (2, 3, 5). When we
828 disregard the axes of `c` and `b` that hold the vectors of coefficients,
829 the shapes of the collections are (2,) and (3,), respectively, which are
830 not compatible for broadcasting. To have a broadcast result with shape
831 (2, 3), we add a trivial dimension to `c`: ``c[:, np.newaxis, :]`` has
832 shape (2, 1, 5). The last dimension holds the coefficients of the
833 circulant matrices, so when we call `solve_circulant`, we can use the
834 default ``caxis=-1``. The coefficients of the `b` vectors are in the last
835 dimension of the array `b`, so we use ``baxis=-1``. If we use the
836 default `outaxis`, the result will have shape (5, 2, 3), so we'll use
837 ``outaxis=-1`` to put the solution vectors in the last dimension.
839 >>> x = solve_circulant(c[:, np.newaxis, :], b, baxis=-1, outaxis=-1)
840 >>> x.shape
841 (2, 3, 5)
842 >>> np.set_printoptions(precision=3) # For compact output of numbers.
843 >>> x
844 array([[[-0.118, 0.22 , 1.277, -0.142, 0.302],
845 [ 0.651, 0.989, 2.046, 0.627, 1.072],
846 [ 1.42 , 1.758, 2.816, 1.396, 1.841]],
847 [[ 0.401, 0.304, 0.694, -0.867, 0.377],
848 [ 0.856, 0.758, 1.149, -0.412, 0.831],
849 [ 1.31 , 1.213, 1.603, 0.042, 1.286]]])
851 Check by solving one pair of `c` and `b` vectors (cf. ``x[1, 1, :]``):
853 >>> solve_circulant(c[1], b[1, :])
854 array([ 0.856, 0.758, 1.149, -0.412, 0.831])
856 """
857 c = np.atleast_1d(c)
858 nc = _get_axis_len("c", c, caxis)
859 b = np.atleast_1d(b)
860 nb = _get_axis_len("b", b, baxis)
861 if nc != nb:
862 raise ValueError('Shapes of c {} and b {} are incompatible'
863 .format(c.shape, b.shape))
865 fc = np.fft.fft(np.moveaxis(c, caxis, -1), axis=-1)
866 abs_fc = np.abs(fc)
867 if tol is None:
868 # This is the same tolerance as used in np.linalg.matrix_rank.
869 tol = abs_fc.max(axis=-1) * nc * np.finfo(np.float64).eps
870 if tol.shape != ():
871 tol.shape = tol.shape + (1,)
872 else:
873 tol = np.atleast_1d(tol)
875 near_zeros = abs_fc <= tol
876 is_near_singular = np.any(near_zeros)
877 if is_near_singular:
878 if singular == 'raise':
879 raise LinAlgError("near singular circulant matrix.")
880 else:
881 # Replace the small values with 1 to avoid errors in the
882 # division fb/fc below.
883 fc[near_zeros] = 1
885 fb = np.fft.fft(np.moveaxis(b, baxis, -1), axis=-1)
887 q = fb / fc
889 if is_near_singular:
890 # `near_zeros` is a boolean array, same shape as `c`, that is
891 # True where `fc` is (near) zero. `q` is the broadcasted result
892 # of fb / fc, so to set the values of `q` to 0 where `fc` is near
893 # zero, we use a mask that is the broadcast result of an array
894 # of True values shaped like `b` with `near_zeros`.
895 mask = np.ones_like(b, dtype=bool) & near_zeros
896 q[mask] = 0
898 x = np.fft.ifft(q, axis=-1)
899 if not (np.iscomplexobj(c) or np.iscomplexobj(b)):
900 x = x.real
901 if outaxis != -1:
902 x = np.moveaxis(x, -1, outaxis)
903 return x
906# matrix inversion
907def inv(a, overwrite_a=False, check_finite=True):
908 """
909 Compute the inverse of a matrix.
911 Parameters
912 ----------
913 a : array_like
914 Square matrix to be inverted.
915 overwrite_a : bool, optional
916 Discard data in `a` (may improve performance). Default is False.
917 check_finite : bool, optional
918 Whether to check that the input matrix contains only finite numbers.
919 Disabling may give a performance gain, but may result in problems
920 (crashes, non-termination) if the inputs do contain infinities or NaNs.
922 Returns
923 -------
924 ainv : ndarray
925 Inverse of the matrix `a`.
927 Raises
928 ------
929 LinAlgError
930 If `a` is singular.
931 ValueError
932 If `a` is not square, or not 2D.
934 Examples
935 --------
936 >>> import numpy as np
937 >>> from scipy import linalg
938 >>> a = np.array([[1., 2.], [3., 4.]])
939 >>> linalg.inv(a)
940 array([[-2. , 1. ],
941 [ 1.5, -0.5]])
942 >>> np.dot(a, linalg.inv(a))
943 array([[ 1., 0.],
944 [ 0., 1.]])
946 """
947 a1 = _asarray_validated(a, check_finite=check_finite)
948 if len(a1.shape) != 2 or a1.shape[0] != a1.shape[1]:
949 raise ValueError('expected square matrix')
950 overwrite_a = overwrite_a or _datacopied(a1, a)
951 # XXX: I found no advantage or disadvantage of using finv.
952# finv, = get_flinalg_funcs(('inv',),(a1,))
953# if finv is not None:
954# a_inv,info = finv(a1,overwrite_a=overwrite_a)
955# if info==0:
956# return a_inv
957# if info>0: raise LinAlgError, "singular matrix"
958# if info<0: raise ValueError('illegal value in %d-th argument of '
959# 'internal inv.getrf|getri'%(-info))
960 getrf, getri, getri_lwork = get_lapack_funcs(('getrf', 'getri',
961 'getri_lwork'),
962 (a1,))
963 lu, piv, info = getrf(a1, overwrite_a=overwrite_a)
964 if info == 0:
965 lwork = _compute_lwork(getri_lwork, a1.shape[0])
967 # XXX: the following line fixes curious SEGFAULT when
968 # benchmarking 500x500 matrix inverse. This seems to
969 # be a bug in LAPACK ?getri routine because if lwork is
970 # minimal (when using lwork[0] instead of lwork[1]) then
971 # all tests pass. Further investigation is required if
972 # more such SEGFAULTs occur.
973 lwork = int(1.01 * lwork)
974 inv_a, info = getri(lu, piv, lwork=lwork, overwrite_lu=1)
975 if info > 0:
976 raise LinAlgError("singular matrix")
977 if info < 0:
978 raise ValueError('illegal value in %d-th argument of internal '
979 'getrf|getri' % -info)
980 return inv_a
983# Determinant
985def det(a, overwrite_a=False, check_finite=True):
986 """
987 Compute the determinant of a matrix
989 The determinant is a scalar that is a function of the associated square
990 matrix coefficients. The determinant value is zero for singular matrices.
992 Parameters
993 ----------
994 a : (..., M, M) array_like
995 Input array to compute determinants for.
996 overwrite_a : bool, optional
997 Allow overwriting data in a (may enhance performance).
998 check_finite : bool, optional
999 Whether to check that the input matrix contains only finite numbers.
1000 Disabling may give a performance gain, but may result in problems
1001 (crashes, non-termination) if the inputs do contain infinities or NaNs.
1003 Returns
1004 -------
1005 det : (...) float or complex
1006 Determinant of `a`. For stacked arrays, a scalar is returned for each
1007 (m, m) slice in the last two dimensions of the input. For example, an
1008 input of shape (p, q, m, m) will produce a result of shape (p, q). If
1009 all dimensions are 1 a scalar is returned regardless of ndim.
1011 Notes
1012 -----
1013 The determinant is computed by performing an LU factorization of the
1014 input with LAPACK routine 'getrf', and then calculating the product of
1015 diagonal entries of the U factor.
1017 Even the input array is single precision (float32 or complex64), the result
1018 will be returned in double precision (float64 or complex128) to prevent
1019 overflows.
1021 Examples
1022 --------
1023 >>> import numpy as np
1024 >>> from scipy import linalg
1025 >>> a = np.array([[1,2,3], [4,5,6], [7,8,9]]) # A singular matrix
1026 >>> linalg.det(a)
1027 0.0
1028 >>> b = np.array([[0,2,3], [4,5,6], [7,8,9]])
1029 >>> linalg.det(b)
1030 3.0
1031 >>> # An array with the shape (3, 2, 2, 2)
1032 >>> c = np.array([[[[1., 2.], [3., 4.]],
1033 ... [[5., 6.], [7., 8.]]],
1034 ... [[[9., 10.], [11., 12.]],
1035 ... [[13., 14.], [15., 16.]]],
1036 ... [[[17., 18.], [19., 20.]],
1037 ... [[21., 22.], [23., 24.]]]])
1038 >>> linalg.det(c) # The resulting shape is (3, 2)
1039 array([[-2., -2.],
1040 [-2., -2.],
1041 [-2., -2.]])
1042 >>> linalg.det(c[0, 0]) # Confirm the (0, 0) slice, [[1, 2], [3, 4]]
1043 -2.0
1044 """
1045 # The goal is to end up with a writable contiguous array to pass to Cython
1047 # First we check and make arrays.
1048 a1 = np.asarray_chkfinite(a) if check_finite else np.asarray(a)
1049 if a1.ndim < 2:
1050 raise ValueError('The input array must be at least two-dimensional.')
1051 if a1.shape[-1] != a1.shape[-2]:
1052 raise ValueError('Last 2 dimensions of the array must be square'
1053 f' but received shape {a1.shape}.')
1055 # Also check if dtype is LAPACK compatible
1056 if a1.dtype.char not in 'fdFD':
1057 dtype_char = lapack_cast_dict[a1.dtype.char]
1058 if not dtype_char: # No casting possible
1059 raise TypeError(f'The dtype "{a1.dtype.name}" cannot be cast '
1060 'to float(32, 64) or complex(64, 128).')
1062 a1 = a1.astype(dtype_char[0]) # makes a copy, free to scratch
1063 overwrite_a = True
1065 # Empty array has determinant 1 because math.
1066 if min(*a1.shape) == 0:
1067 if a1.ndim == 2:
1068 return np.float64(1.)
1069 else:
1070 return np.ones(shape=a1.shape[:-2], dtype=np.float64)
1072 # Scalar case
1073 if a1.shape[-2:] == (1, 1):
1074 # Either ndarray with spurious singletons or a single element
1075 if max(*a1.shape) > 1:
1076 temp = np.squeeze(a1)
1077 if a1.dtype.char in 'dD':
1078 return temp
1079 else:
1080 return (temp.astype('d') if a1.dtype.char == 'f' else
1081 temp.astype('D'))
1082 else:
1083 return (np.float64(a1.item()) if a1.dtype.char in 'fd' else
1084 np.complex128(a1.item()))
1086 # Then check overwrite permission
1087 if not _datacopied(a1, a): # "a" still alive through "a1"
1088 if not overwrite_a:
1089 # Data belongs to "a" so make a copy
1090 a1 = a1.copy(order='C')
1091 # else: Do nothing we'll use "a" if possible
1092 # else: a1 has its own data thus free to scratch
1094 # Then layout checks, might happen that overwrite is allowed but original
1095 # array was read-only or non-C-contiguous.
1096 if not (a1.flags['C_CONTIGUOUS'] and a1.flags['WRITEABLE']):
1097 a1 = a1.copy(order='C')
1099 if a1.ndim == 2:
1100 det = find_det_from_lu(a1)
1101 # Convert float, complex to to NumPy scalars
1102 return (np.float64(det) if np.isrealobj(det) else np.complex128(det))
1104 # loop over the stacked array, and avoid overflows for single precision
1105 # Cf. np.linalg.det(np.diag([1e+38, 1e+38]).astype(np.float32))
1106 dtype_char = a1.dtype.char
1107 if dtype_char in 'fF':
1108 dtype_char = 'd' if dtype_char.islower() else 'D'
1110 det = np.empty(a1.shape[:-2], dtype=dtype_char)
1111 for ind in product(*[range(x) for x in a1.shape[:-2]]):
1112 det[ind] = find_det_from_lu(a1[ind])
1113 return det
1116# Linear Least Squares
1117def lstsq(a, b, cond=None, overwrite_a=False, overwrite_b=False,
1118 check_finite=True, lapack_driver=None):
1119 """
1120 Compute least-squares solution to equation Ax = b.
1122 Compute a vector x such that the 2-norm ``|b - A x|`` is minimized.
1124 Parameters
1125 ----------
1126 a : (M, N) array_like
1127 Left-hand side array
1128 b : (M,) or (M, K) array_like
1129 Right hand side array
1130 cond : float, optional
1131 Cutoff for 'small' singular values; used to determine effective
1132 rank of a. Singular values smaller than
1133 ``cond * largest_singular_value`` are considered zero.
1134 overwrite_a : bool, optional
1135 Discard data in `a` (may enhance performance). Default is False.
1136 overwrite_b : bool, optional
1137 Discard data in `b` (may enhance performance). Default is False.
1138 check_finite : bool, optional
1139 Whether to check that the input matrices contain only finite numbers.
1140 Disabling may give a performance gain, but may result in problems
1141 (crashes, non-termination) if the inputs do contain infinities or NaNs.
1142 lapack_driver : str, optional
1143 Which LAPACK driver is used to solve the least-squares problem.
1144 Options are ``'gelsd'``, ``'gelsy'``, ``'gelss'``. Default
1145 (``'gelsd'``) is a good choice. However, ``'gelsy'`` can be slightly
1146 faster on many problems. ``'gelss'`` was used historically. It is
1147 generally slow but uses less memory.
1149 .. versionadded:: 0.17.0
1151 Returns
1152 -------
1153 x : (N,) or (N, K) ndarray
1154 Least-squares solution.
1155 residues : (K,) ndarray or float
1156 Square of the 2-norm for each column in ``b - a x``, if ``M > N`` and
1157 ``ndim(A) == n`` (returns a scalar if ``b`` is 1-D). Otherwise a
1158 (0,)-shaped array is returned.
1159 rank : int
1160 Effective rank of `a`.
1161 s : (min(M, N),) ndarray or None
1162 Singular values of `a`. The condition number of ``a`` is
1163 ``s[0] / s[-1]``.
1165 Raises
1166 ------
1167 LinAlgError
1168 If computation does not converge.
1170 ValueError
1171 When parameters are not compatible.
1173 See Also
1174 --------
1175 scipy.optimize.nnls : linear least squares with non-negativity constraint
1177 Notes
1178 -----
1179 When ``'gelsy'`` is used as a driver, `residues` is set to a (0,)-shaped
1180 array and `s` is always ``None``.
1182 Examples
1183 --------
1184 >>> import numpy as np
1185 >>> from scipy.linalg import lstsq
1186 >>> import matplotlib.pyplot as plt
1188 Suppose we have the following data:
1190 >>> x = np.array([1, 2.5, 3.5, 4, 5, 7, 8.5])
1191 >>> y = np.array([0.3, 1.1, 1.5, 2.0, 3.2, 6.6, 8.6])
1193 We want to fit a quadratic polynomial of the form ``y = a + b*x**2``
1194 to this data. We first form the "design matrix" M, with a constant
1195 column of 1s and a column containing ``x**2``:
1197 >>> M = x[:, np.newaxis]**[0, 2]
1198 >>> M
1199 array([[ 1. , 1. ],
1200 [ 1. , 6.25],
1201 [ 1. , 12.25],
1202 [ 1. , 16. ],
1203 [ 1. , 25. ],
1204 [ 1. , 49. ],
1205 [ 1. , 72.25]])
1207 We want to find the least-squares solution to ``M.dot(p) = y``,
1208 where ``p`` is a vector with length 2 that holds the parameters
1209 ``a`` and ``b``.
1211 >>> p, res, rnk, s = lstsq(M, y)
1212 >>> p
1213 array([ 0.20925829, 0.12013861])
1215 Plot the data and the fitted curve.
1217 >>> plt.plot(x, y, 'o', label='data')
1218 >>> xx = np.linspace(0, 9, 101)
1219 >>> yy = p[0] + p[1]*xx**2
1220 >>> plt.plot(xx, yy, label='least squares fit, $y = a + bx^2$')
1221 >>> plt.xlabel('x')
1222 >>> plt.ylabel('y')
1223 >>> plt.legend(framealpha=1, shadow=True)
1224 >>> plt.grid(alpha=0.25)
1225 >>> plt.show()
1227 """
1228 a1 = _asarray_validated(a, check_finite=check_finite)
1229 b1 = _asarray_validated(b, check_finite=check_finite)
1230 if len(a1.shape) != 2:
1231 raise ValueError('Input array a should be 2D')
1232 m, n = a1.shape
1233 if len(b1.shape) == 2:
1234 nrhs = b1.shape[1]
1235 else:
1236 nrhs = 1
1237 if m != b1.shape[0]:
1238 raise ValueError('Shape mismatch: a and b should have the same number'
1239 ' of rows ({} != {}).'.format(m, b1.shape[0]))
1240 if m == 0 or n == 0: # Zero-sized problem, confuses LAPACK
1241 x = np.zeros((n,) + b1.shape[1:], dtype=np.common_type(a1, b1))
1242 if n == 0:
1243 residues = np.linalg.norm(b1, axis=0)**2
1244 else:
1245 residues = np.empty((0,))
1246 return x, residues, 0, np.empty((0,))
1248 driver = lapack_driver
1249 if driver is None:
1250 driver = lstsq.default_lapack_driver
1251 if driver not in ('gelsd', 'gelsy', 'gelss'):
1252 raise ValueError('LAPACK driver "%s" is not found' % driver)
1254 lapack_func, lapack_lwork = get_lapack_funcs((driver,
1255 '%s_lwork' % driver),
1256 (a1, b1))
1257 real_data = True if (lapack_func.dtype.kind == 'f') else False
1259 if m < n:
1260 # need to extend b matrix as it will be filled with
1261 # a larger solution matrix
1262 if len(b1.shape) == 2:
1263 b2 = np.zeros((n, nrhs), dtype=lapack_func.dtype)
1264 b2[:m, :] = b1
1265 else:
1266 b2 = np.zeros(n, dtype=lapack_func.dtype)
1267 b2[:m] = b1
1268 b1 = b2
1270 overwrite_a = overwrite_a or _datacopied(a1, a)
1271 overwrite_b = overwrite_b or _datacopied(b1, b)
1273 if cond is None:
1274 cond = np.finfo(lapack_func.dtype).eps
1276 if driver in ('gelss', 'gelsd'):
1277 if driver == 'gelss':
1278 lwork = _compute_lwork(lapack_lwork, m, n, nrhs, cond)
1279 v, x, s, rank, work, info = lapack_func(a1, b1, cond, lwork,
1280 overwrite_a=overwrite_a,
1281 overwrite_b=overwrite_b)
1283 elif driver == 'gelsd':
1284 if real_data:
1285 lwork, iwork = _compute_lwork(lapack_lwork, m, n, nrhs, cond)
1286 x, s, rank, info = lapack_func(a1, b1, lwork,
1287 iwork, cond, False, False)
1288 else: # complex data
1289 lwork, rwork, iwork = _compute_lwork(lapack_lwork, m, n,
1290 nrhs, cond)
1291 x, s, rank, info = lapack_func(a1, b1, lwork, rwork, iwork,
1292 cond, False, False)
1293 if info > 0:
1294 raise LinAlgError("SVD did not converge in Linear Least Squares")
1295 if info < 0:
1296 raise ValueError('illegal value in %d-th argument of internal %s'
1297 % (-info, lapack_driver))
1298 resids = np.asarray([], dtype=x.dtype)
1299 if m > n:
1300 x1 = x[:n]
1301 if rank == n:
1302 resids = np.sum(np.abs(x[n:])**2, axis=0)
1303 x = x1
1304 return x, resids, rank, s
1306 elif driver == 'gelsy':
1307 lwork = _compute_lwork(lapack_lwork, m, n, nrhs, cond)
1308 jptv = np.zeros((a1.shape[1], 1), dtype=np.int32)
1309 v, x, j, rank, info = lapack_func(a1, b1, jptv, cond,
1310 lwork, False, False)
1311 if info < 0:
1312 raise ValueError("illegal value in %d-th argument of internal "
1313 "gelsy" % -info)
1314 if m > n:
1315 x1 = x[:n]
1316 x = x1
1317 return x, np.array([], x.dtype), rank, None
1320lstsq.default_lapack_driver = 'gelsd'
1323@_deprecate_positional_args(version="1.14")
1324def pinv(a, *, atol=None, rtol=None, return_rank=False, check_finite=True,
1325 cond=_NoValue, rcond=_NoValue):
1326 """
1327 Compute the (Moore-Penrose) pseudo-inverse of a matrix.
1329 Calculate a generalized inverse of a matrix using its
1330 singular-value decomposition ``U @ S @ V`` in the economy mode and picking
1331 up only the columns/rows that are associated with significant singular
1332 values.
1334 If ``s`` is the maximum singular value of ``a``, then the
1335 significance cut-off value is determined by ``atol + rtol * s``. Any
1336 singular value below this value is assumed insignificant.
1338 Parameters
1339 ----------
1340 a : (M, N) array_like
1341 Matrix to be pseudo-inverted.
1342 atol : float, optional
1343 Absolute threshold term, default value is 0.
1345 .. versionadded:: 1.7.0
1347 rtol : float, optional
1348 Relative threshold term, default value is ``max(M, N) * eps`` where
1349 ``eps`` is the machine precision value of the datatype of ``a``.
1351 .. versionadded:: 1.7.0
1353 return_rank : bool, optional
1354 If True, return the effective rank of the matrix.
1355 check_finite : bool, optional
1356 Whether to check that the input matrix contains only finite numbers.
1357 Disabling may give a performance gain, but may result in problems
1358 (crashes, non-termination) if the inputs do contain infinities or NaNs.
1359 cond, rcond : float, optional
1360 In older versions, these values were meant to be used as ``atol`` with
1361 ``rtol=0``. If both were given ``rcond`` overwrote ``cond`` and hence
1362 the code was not correct. Thus using these are strongly discouraged and
1363 the tolerances above are recommended instead. In fact, if provided,
1364 atol, rtol takes precedence over these keywords.
1366 .. deprecated:: 1.7.0
1367 Deprecated in favor of ``rtol`` and ``atol`` parameters above and
1368 will be removed in SciPy 1.14.0.
1370 .. versionchanged:: 1.3.0
1371 Previously the default cutoff value was just ``eps*f`` where ``f``
1372 was ``1e3`` for single precision and ``1e6`` for double precision.
1374 Returns
1375 -------
1376 B : (N, M) ndarray
1377 The pseudo-inverse of matrix `a`.
1378 rank : int
1379 The effective rank of the matrix. Returned if `return_rank` is True.
1381 Raises
1382 ------
1383 LinAlgError
1384 If SVD computation does not converge.
1386 See Also
1387 --------
1388 pinvh : Moore-Penrose pseudoinverse of a hermitian matrix.
1390 Notes
1391 -----
1392 If ``A`` is invertible then the Moore-Penrose pseudoinverse is exactly
1393 the inverse of ``A`` [1]_. If ``A`` is not invertible then the
1394 Moore-Penrose pseudoinverse computes the ``x`` solution to ``Ax = b`` such
1395 that ``||Ax - b||`` is minimized [1]_.
1397 References
1398 ----------
1399 .. [1] Penrose, R. (1956). On best approximate solutions of linear matrix
1400 equations. Mathematical Proceedings of the Cambridge Philosophical
1401 Society, 52(1), 17-19. doi:10.1017/S0305004100030929
1403 Examples
1404 --------
1406 Given an ``m x n`` matrix ``A`` and an ``n x m`` matrix ``B`` the four
1407 Moore-Penrose conditions are:
1409 1. ``ABA = A`` (``B`` is a generalized inverse of ``A``),
1410 2. ``BAB = B`` (``A`` is a generalized inverse of ``B``),
1411 3. ``(AB)* = AB`` (``AB`` is hermitian),
1412 4. ``(BA)* = BA`` (``BA`` is hermitian) [1]_.
1414 Here, ``A*`` denotes the conjugate transpose. The Moore-Penrose
1415 pseudoinverse is a unique ``B`` that satisfies all four of these
1416 conditions and exists for any ``A``. Note that, unlike the standard
1417 matrix inverse, ``A`` does not have to be a square matrix or have
1418 linearly independent columns/rows.
1420 As an example, we can calculate the Moore-Penrose pseudoinverse of a
1421 random non-square matrix and verify it satisfies the four conditions.
1423 >>> import numpy as np
1424 >>> from scipy import linalg
1425 >>> rng = np.random.default_rng()
1426 >>> A = rng.standard_normal((9, 6))
1427 >>> B = linalg.pinv(A)
1428 >>> np.allclose(A @ B @ A, A) # Condition 1
1429 True
1430 >>> np.allclose(B @ A @ B, B) # Condition 2
1431 True
1432 >>> np.allclose((A @ B).conj().T, A @ B) # Condition 3
1433 True
1434 >>> np.allclose((B @ A).conj().T, B @ A) # Condition 4
1435 True
1437 """
1438 a = _asarray_validated(a, check_finite=check_finite)
1439 u, s, vh = _decomp_svd.svd(a, full_matrices=False, check_finite=False)
1440 t = u.dtype.char.lower()
1441 maxS = np.max(s)
1443 if rcond is not _NoValue or cond is not _NoValue:
1444 warn('Use of the "cond" and "rcond" keywords are deprecated and '
1445 'will be removed in SciPy 1.14.0. Use "atol" and '
1446 '"rtol" keywords instead', DeprecationWarning, stacklevel=2)
1448 # backwards compatible only atol and rtol are both missing
1449 if ((rcond not in (_NoValue, None) or cond not in (_NoValue, None))
1450 and (atol is None) and (rtol is None)):
1451 atol = rcond if rcond not in (_NoValue, None) else cond
1452 rtol = 0.
1454 atol = 0. if atol is None else atol
1455 rtol = max(a.shape) * np.finfo(t).eps if (rtol is None) else rtol
1457 if (atol < 0.) or (rtol < 0.):
1458 raise ValueError("atol and rtol values must be positive.")
1460 val = atol + maxS * rtol
1461 rank = np.sum(s > val)
1463 u = u[:, :rank]
1464 u /= s[:rank]
1465 B = (u @ vh[:rank]).conj().T
1467 if return_rank:
1468 return B, rank
1469 else:
1470 return B
1473def pinvh(a, atol=None, rtol=None, lower=True, return_rank=False,
1474 check_finite=True):
1475 """
1476 Compute the (Moore-Penrose) pseudo-inverse of a Hermitian matrix.
1478 Calculate a generalized inverse of a complex Hermitian/real symmetric
1479 matrix using its eigenvalue decomposition and including all eigenvalues
1480 with 'large' absolute value.
1482 Parameters
1483 ----------
1484 a : (N, N) array_like
1485 Real symmetric or complex hermetian matrix to be pseudo-inverted
1487 atol : float, optional
1488 Absolute threshold term, default value is 0.
1490 .. versionadded:: 1.7.0
1492 rtol : float, optional
1493 Relative threshold term, default value is ``N * eps`` where
1494 ``eps`` is the machine precision value of the datatype of ``a``.
1496 .. versionadded:: 1.7.0
1498 lower : bool, optional
1499 Whether the pertinent array data is taken from the lower or upper
1500 triangle of `a`. (Default: lower)
1501 return_rank : bool, optional
1502 If True, return the effective rank of the matrix.
1503 check_finite : bool, optional
1504 Whether to check that the input matrix contains only finite numbers.
1505 Disabling may give a performance gain, but may result in problems
1506 (crashes, non-termination) if the inputs do contain infinities or NaNs.
1508 Returns
1509 -------
1510 B : (N, N) ndarray
1511 The pseudo-inverse of matrix `a`.
1512 rank : int
1513 The effective rank of the matrix. Returned if `return_rank` is True.
1515 Raises
1516 ------
1517 LinAlgError
1518 If eigenvalue algorithm does not converge.
1520 See Also
1521 --------
1522 pinv : Moore-Penrose pseudoinverse of a matrix.
1524 Examples
1525 --------
1527 For a more detailed example see `pinv`.
1529 >>> import numpy as np
1530 >>> from scipy.linalg import pinvh
1531 >>> rng = np.random.default_rng()
1532 >>> a = rng.standard_normal((9, 6))
1533 >>> a = np.dot(a, a.T)
1534 >>> B = pinvh(a)
1535 >>> np.allclose(a, a @ B @ a)
1536 True
1537 >>> np.allclose(B, B @ a @ B)
1538 True
1540 """
1541 a = _asarray_validated(a, check_finite=check_finite)
1542 s, u = _decomp.eigh(a, lower=lower, check_finite=False)
1543 t = u.dtype.char.lower()
1544 maxS = np.max(np.abs(s))
1546 atol = 0. if atol is None else atol
1547 rtol = max(a.shape) * np.finfo(t).eps if (rtol is None) else rtol
1549 if (atol < 0.) or (rtol < 0.):
1550 raise ValueError("atol and rtol values must be positive.")
1552 val = atol + maxS * rtol
1553 above_cutoff = (abs(s) > val)
1555 psigma_diag = 1.0 / s[above_cutoff]
1556 u = u[:, above_cutoff]
1558 B = (u * psigma_diag) @ u.conj().T
1560 if return_rank:
1561 return B, len(psigma_diag)
1562 else:
1563 return B
1566def matrix_balance(A, permute=True, scale=True, separate=False,
1567 overwrite_a=False):
1568 """
1569 Compute a diagonal similarity transformation for row/column balancing.
1571 The balancing tries to equalize the row and column 1-norms by applying
1572 a similarity transformation such that the magnitude variation of the
1573 matrix entries is reflected to the scaling matrices.
1575 Moreover, if enabled, the matrix is first permuted to isolate the upper
1576 triangular parts of the matrix and, again if scaling is also enabled,
1577 only the remaining subblocks are subjected to scaling.
1579 The balanced matrix satisfies the following equality
1581 .. math::
1583 B = T^{-1} A T
1585 The scaling coefficients are approximated to the nearest power of 2
1586 to avoid round-off errors.
1588 Parameters
1589 ----------
1590 A : (n, n) array_like
1591 Square data matrix for the balancing.
1592 permute : bool, optional
1593 The selector to define whether permutation of A is also performed
1594 prior to scaling.
1595 scale : bool, optional
1596 The selector to turn on and off the scaling. If False, the matrix
1597 will not be scaled.
1598 separate : bool, optional
1599 This switches from returning a full matrix of the transformation
1600 to a tuple of two separate 1-D permutation and scaling arrays.
1601 overwrite_a : bool, optional
1602 This is passed to xGEBAL directly. Essentially, overwrites the result
1603 to the data. It might increase the space efficiency. See LAPACK manual
1604 for details. This is False by default.
1606 Returns
1607 -------
1608 B : (n, n) ndarray
1609 Balanced matrix
1610 T : (n, n) ndarray
1611 A possibly permuted diagonal matrix whose nonzero entries are
1612 integer powers of 2 to avoid numerical truncation errors.
1613 scale, perm : (n,) ndarray
1614 If ``separate`` keyword is set to True then instead of the array
1615 ``T`` above, the scaling and the permutation vectors are given
1616 separately as a tuple without allocating the full array ``T``.
1618 Notes
1619 -----
1620 This algorithm is particularly useful for eigenvalue and matrix
1621 decompositions and in many cases it is already called by various
1622 LAPACK routines.
1624 The algorithm is based on the well-known technique of [1]_ and has
1625 been modified to account for special cases. See [2]_ for details
1626 which have been implemented since LAPACK v3.5.0. Before this version
1627 there are corner cases where balancing can actually worsen the
1628 conditioning. See [3]_ for such examples.
1630 The code is a wrapper around LAPACK's xGEBAL routine family for matrix
1631 balancing.
1633 .. versionadded:: 0.19.0
1635 References
1636 ----------
1637 .. [1] B.N. Parlett and C. Reinsch, "Balancing a Matrix for
1638 Calculation of Eigenvalues and Eigenvectors", Numerische Mathematik,
1639 Vol.13(4), 1969, :doi:`10.1007/BF02165404`
1640 .. [2] R. James, J. Langou, B.R. Lowery, "On matrix balancing and
1641 eigenvector computation", 2014, :arxiv:`1401.5766`
1642 .. [3] D.S. Watkins. A case where balancing is harmful.
1643 Electron. Trans. Numer. Anal, Vol.23, 2006.
1645 Examples
1646 --------
1647 >>> import numpy as np
1648 >>> from scipy import linalg
1649 >>> x = np.array([[1,2,0], [9,1,0.01], [1,2,10*np.pi]])
1651 >>> y, permscale = linalg.matrix_balance(x)
1652 >>> np.abs(x).sum(axis=0) / np.abs(x).sum(axis=1)
1653 array([ 3.66666667, 0.4995005 , 0.91312162])
1655 >>> np.abs(y).sum(axis=0) / np.abs(y).sum(axis=1)
1656 array([ 1.2 , 1.27041742, 0.92658316]) # may vary
1658 >>> permscale # only powers of 2 (0.5 == 2^(-1))
1659 array([[ 0.5, 0. , 0. ], # may vary
1660 [ 0. , 1. , 0. ],
1661 [ 0. , 0. , 1. ]])
1663 """
1665 A = np.atleast_2d(_asarray_validated(A, check_finite=True))
1667 if not np.equal(*A.shape):
1668 raise ValueError('The data matrix for balancing should be square.')
1670 gebal = get_lapack_funcs(('gebal'), (A,))
1671 B, lo, hi, ps, info = gebal(A, scale=scale, permute=permute,
1672 overwrite_a=overwrite_a)
1674 if info < 0:
1675 raise ValueError('xGEBAL exited with the internal error '
1676 '"illegal value in argument number {}.". See '
1677 'LAPACK documentation for the xGEBAL error codes.'
1678 ''.format(-info))
1680 # Separate the permutations from the scalings and then convert to int
1681 scaling = np.ones_like(ps, dtype=float)
1682 scaling[lo:hi+1] = ps[lo:hi+1]
1684 # gebal uses 1-indexing
1685 ps = ps.astype(int, copy=False) - 1
1686 n = A.shape[0]
1687 perm = np.arange(n)
1689 # LAPACK permutes with the ordering n --> hi, then 0--> lo
1690 if hi < n:
1691 for ind, x in enumerate(ps[hi+1:][::-1], 1):
1692 if n-ind == x:
1693 continue
1694 perm[[x, n-ind]] = perm[[n-ind, x]]
1696 if lo > 0:
1697 for ind, x in enumerate(ps[:lo]):
1698 if ind == x:
1699 continue
1700 perm[[x, ind]] = perm[[ind, x]]
1702 if separate:
1703 return B, (scaling, perm)
1705 # get the inverse permutation
1706 iperm = np.empty_like(perm)
1707 iperm[perm] = np.arange(n)
1709 return B, np.diag(scaling)[iperm, :]
1712def _validate_args_for_toeplitz_ops(c_or_cr, b, check_finite, keep_b_shape,
1713 enforce_square=True):
1714 """Validate arguments and format inputs for toeplitz functions
1716 Parameters
1717 ----------
1718 c_or_cr : array_like or tuple of (array_like, array_like)
1719 The vector ``c``, or a tuple of arrays (``c``, ``r``). Whatever the
1720 actual shape of ``c``, it will be converted to a 1-D array. If not
1721 supplied, ``r = conjugate(c)`` is assumed; in this case, if c[0] is
1722 real, the Toeplitz matrix is Hermitian. r[0] is ignored; the first row
1723 of the Toeplitz matrix is ``[c[0], r[1:]]``. Whatever the actual shape
1724 of ``r``, it will be converted to a 1-D array.
1725 b : (M,) or (M, K) array_like
1726 Right-hand side in ``T x = b``.
1727 check_finite : bool
1728 Whether to check that the input matrices contain only finite numbers.
1729 Disabling may give a performance gain, but may result in problems
1730 (result entirely NaNs) if the inputs do contain infinities or NaNs.
1731 keep_b_shape : bool
1732 Whether to convert a (M,) dimensional b into a (M, 1) dimensional
1733 matrix.
1734 enforce_square : bool, optional
1735 If True (default), this verifies that the Toeplitz matrix is square.
1737 Returns
1738 -------
1739 r : array
1740 1d array corresponding to the first row of the Toeplitz matrix.
1741 c: array
1742 1d array corresponding to the first column of the Toeplitz matrix.
1743 b: array
1744 (M,), (M, 1) or (M, K) dimensional array, post validation,
1745 corresponding to ``b``.
1746 dtype: numpy datatype
1747 ``dtype`` stores the datatype of ``r``, ``c`` and ``b``. If any of
1748 ``r``, ``c`` or ``b`` are complex, ``dtype`` is ``np.complex128``,
1749 otherwise, it is ``np.float``.
1750 b_shape: tuple
1751 Shape of ``b`` after passing it through ``_asarray_validated``.
1753 """
1755 if isinstance(c_or_cr, tuple):
1756 c, r = c_or_cr
1757 c = _asarray_validated(c, check_finite=check_finite).ravel()
1758 r = _asarray_validated(r, check_finite=check_finite).ravel()
1759 else:
1760 c = _asarray_validated(c_or_cr, check_finite=check_finite).ravel()
1761 r = c.conjugate()
1763 if b is None:
1764 raise ValueError('`b` must be an array, not None.')
1766 b = _asarray_validated(b, check_finite=check_finite)
1767 b_shape = b.shape
1769 is_not_square = r.shape[0] != c.shape[0]
1770 if (enforce_square and is_not_square) or b.shape[0] != r.shape[0]:
1771 raise ValueError('Incompatible dimensions.')
1773 is_cmplx = np.iscomplexobj(r) or np.iscomplexobj(c) or np.iscomplexobj(b)
1774 dtype = np.complex128 if is_cmplx else np.float64
1775 r, c, b = (np.asarray(i, dtype=dtype) for i in (r, c, b))
1777 if b.ndim == 1 and not keep_b_shape:
1778 b = b.reshape(-1, 1)
1779 elif b.ndim != 1:
1780 b = b.reshape(b.shape[0], -1)
1782 return r, c, b, dtype, b_shape
1785def matmul_toeplitz(c_or_cr, x, check_finite=False, workers=None):
1786 """Efficient Toeplitz Matrix-Matrix Multiplication using FFT
1788 This function returns the matrix multiplication between a Toeplitz
1789 matrix and a dense matrix.
1791 The Toeplitz matrix has constant diagonals, with c as its first column
1792 and r as its first row. If r is not given, ``r == conjugate(c)`` is
1793 assumed.
1795 Parameters
1796 ----------
1797 c_or_cr : array_like or tuple of (array_like, array_like)
1798 The vector ``c``, or a tuple of arrays (``c``, ``r``). Whatever the
1799 actual shape of ``c``, it will be converted to a 1-D array. If not
1800 supplied, ``r = conjugate(c)`` is assumed; in this case, if c[0] is
1801 real, the Toeplitz matrix is Hermitian. r[0] is ignored; the first row
1802 of the Toeplitz matrix is ``[c[0], r[1:]]``. Whatever the actual shape
1803 of ``r``, it will be converted to a 1-D array.
1804 x : (M,) or (M, K) array_like
1805 Matrix with which to multiply.
1806 check_finite : bool, optional
1807 Whether to check that the input matrices contain only finite numbers.
1808 Disabling may give a performance gain, but may result in problems
1809 (result entirely NaNs) if the inputs do contain infinities or NaNs.
1810 workers : int, optional
1811 To pass to scipy.fft.fft and ifft. Maximum number of workers to use
1812 for parallel computation. If negative, the value wraps around from
1813 ``os.cpu_count()``. See scipy.fft.fft for more details.
1815 Returns
1816 -------
1817 T @ x : (M,) or (M, K) ndarray
1818 The result of the matrix multiplication ``T @ x``. Shape of return
1819 matches shape of `x`.
1821 See Also
1822 --------
1823 toeplitz : Toeplitz matrix
1824 solve_toeplitz : Solve a Toeplitz system using Levinson Recursion
1826 Notes
1827 -----
1828 The Toeplitz matrix is embedded in a circulant matrix and the FFT is used
1829 to efficiently calculate the matrix-matrix product.
1831 Because the computation is based on the FFT, integer inputs will
1832 result in floating point outputs. This is unlike NumPy's `matmul`,
1833 which preserves the data type of the input.
1835 This is partly based on the implementation that can be found in [1]_,
1836 licensed under the MIT license. More information about the method can be
1837 found in reference [2]_. References [3]_ and [4]_ have more reference
1838 implementations in Python.
1840 .. versionadded:: 1.6.0
1842 References
1843 ----------
1844 .. [1] Jacob R Gardner, Geoff Pleiss, David Bindel, Kilian
1845 Q Weinberger, Andrew Gordon Wilson, "GPyTorch: Blackbox Matrix-Matrix
1846 Gaussian Process Inference with GPU Acceleration" with contributions
1847 from Max Balandat and Ruihan Wu. Available online:
1848 https://github.com/cornellius-gp/gpytorch
1850 .. [2] J. Demmel, P. Koev, and X. Li, "A Brief Survey of Direct Linear
1851 Solvers". In Z. Bai, J. Demmel, J. Dongarra, A. Ruhe, and H. van der
1852 Vorst, editors. Templates for the Solution of Algebraic Eigenvalue
1853 Problems: A Practical Guide. SIAM, Philadelphia, 2000. Available at:
1854 http://www.netlib.org/utk/people/JackDongarra/etemplates/node384.html
1856 .. [3] R. Scheibler, E. Bezzam, I. Dokmanic, Pyroomacoustics: A Python
1857 package for audio room simulations and array processing algorithms,
1858 Proc. IEEE ICASSP, Calgary, CA, 2018.
1859 https://github.com/LCAV/pyroomacoustics/blob/pypi-release/
1860 pyroomacoustics/adaptive/util.py
1862 .. [4] Marano S, Edwards B, Ferrari G and Fah D (2017), "Fitting
1863 Earthquake Spectra: Colored Noise and Incomplete Data", Bulletin of
1864 the Seismological Society of America., January, 2017. Vol. 107(1),
1865 pp. 276-291.
1867 Examples
1868 --------
1869 Multiply the Toeplitz matrix T with matrix x::
1871 [ 1 -1 -2 -3] [1 10]
1872 T = [ 3 1 -1 -2] x = [2 11]
1873 [ 6 3 1 -1] [2 11]
1874 [10 6 3 1] [5 19]
1876 To specify the Toeplitz matrix, only the first column and the first
1877 row are needed.
1879 >>> import numpy as np
1880 >>> c = np.array([1, 3, 6, 10]) # First column of T
1881 >>> r = np.array([1, -1, -2, -3]) # First row of T
1882 >>> x = np.array([[1, 10], [2, 11], [2, 11], [5, 19]])
1884 >>> from scipy.linalg import toeplitz, matmul_toeplitz
1885 >>> matmul_toeplitz((c, r), x)
1886 array([[-20., -80.],
1887 [ -7., -8.],
1888 [ 9., 85.],
1889 [ 33., 218.]])
1891 Check the result by creating the full Toeplitz matrix and
1892 multiplying it by ``x``.
1894 >>> toeplitz(c, r) @ x
1895 array([[-20, -80],
1896 [ -7, -8],
1897 [ 9, 85],
1898 [ 33, 218]])
1900 The full matrix is never formed explicitly, so this routine
1901 is suitable for very large Toeplitz matrices.
1903 >>> n = 1000000
1904 >>> matmul_toeplitz([1] + [0]*(n-1), np.ones(n))
1905 array([1., 1., 1., ..., 1., 1., 1.])
1907 """
1909 from ..fft import fft, ifft, rfft, irfft
1911 r, c, x, dtype, x_shape = _validate_args_for_toeplitz_ops(
1912 c_or_cr, x, check_finite, keep_b_shape=False, enforce_square=False)
1913 n, m = x.shape
1915 T_nrows = len(c)
1916 T_ncols = len(r)
1917 p = T_nrows + T_ncols - 1 # equivalent to len(embedded_col)
1919 embedded_col = np.concatenate((c, r[-1:0:-1]))
1921 if np.iscomplexobj(embedded_col) or np.iscomplexobj(x):
1922 fft_mat = fft(embedded_col, axis=0, workers=workers).reshape(-1, 1)
1923 fft_x = fft(x, n=p, axis=0, workers=workers)
1925 mat_times_x = ifft(fft_mat*fft_x, axis=0,
1926 workers=workers)[:T_nrows, :]
1927 else:
1928 # Real inputs; using rfft is faster
1929 fft_mat = rfft(embedded_col, axis=0, workers=workers).reshape(-1, 1)
1930 fft_x = rfft(x, n=p, axis=0, workers=workers)
1932 mat_times_x = irfft(fft_mat*fft_x, axis=0,
1933 workers=workers, n=p)[:T_nrows, :]
1935 return_shape = (T_nrows,) if len(x_shape) == 1 else (T_nrows, m)
1936 return mat_times_x.reshape(*return_shape)