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