Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/scipy/linalg/_basic.py: 7%
430 statements
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-14 06:37 +0000
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-14 06:37 +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__all__ = ['solve', 'solve_triangular', 'solveh_banded', 'solve_banded',
20 'solve_toeplitz', 'solve_circulant', 'inv', 'det', 'lstsq',
21 'pinv', 'pinvh', 'matrix_balance', 'matmul_toeplitz']
24# The numpy facilities for type-casting checks are too slow for small sized
25# arrays and eat away the time budget for the checkups. Here we set a
26# precomputed dict container of the numpy.can_cast() table.
28# It can be used to determine quickly what a dtype can be cast to LAPACK
29# compatible types, i.e., 'float32, float64, complex64, complex128'.
30# Then it can be checked via "casting_dict[arr.dtype.char]"
31lapack_cast_dict = {x: ''.join([y for y in 'fdFD' if np.can_cast(x, y)])
32 for x in np.typecodes['All']}
35# Linear equations
36def _solve_check(n, info, lamch=None, rcond=None):
37 """ Check arguments during the different steps of the solution phase """
38 if info < 0:
39 raise ValueError(f'LAPACK reported an illegal value in {-info}-th argument.')
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(f'Ill-conditioned matrix (rcond={rcond:.6g}): '
48 'result may not be accurate.',
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(f'{assume_a} is not a recognized matrix structure')
179 # for a real matrix, describe it as "symmetric", not "hermitian"
180 # (lapack doesn't know what to do with real hermitian matrices)
181 if assume_a == 'her' and not np.iscomplexobj(a1):
182 assume_a = 'sym'
184 # Get the correct lamch function.
185 # The LAMCH functions only exists for S and D
186 # So for complex values we have to convert to real/double.
187 if a1.dtype.char in 'fF': # single precision
188 lamch = get_lapack_funcs('lamch', dtype='f')
189 else:
190 lamch = get_lapack_funcs('lamch', dtype='d')
192 # Currently we do not have the other forms of the norm calculators
193 # lansy, lanpo, lanhe.
194 # However, in any case they only reduce computations slightly...
195 lange = get_lapack_funcs('lange', (a1,))
197 # Since the I-norm and 1-norm are the same for symmetric matrices
198 # we can collect them all in this one call
199 # Note however, that when issuing 'gen' and form!='none', then
200 # the I-norm should be used
201 if transposed:
202 trans = 1
203 norm = 'I'
204 if np.iscomplexobj(a1):
205 raise NotImplementedError('scipy.linalg.solve can currently '
206 'not solve a^T x = b or a^H x = b '
207 'for complex matrices.')
208 else:
209 trans = 0
210 norm = '1'
212 anorm = lange(norm, a1)
214 # Generalized case 'gesv'
215 if assume_a == 'gen':
216 gecon, getrf, getrs = get_lapack_funcs(('gecon', 'getrf', 'getrs'),
217 (a1, b1))
218 lu, ipvt, info = getrf(a1, overwrite_a=overwrite_a)
219 _solve_check(n, info)
220 x, info = getrs(lu, ipvt, b1,
221 trans=trans, overwrite_b=overwrite_b)
222 _solve_check(n, info)
223 rcond, info = gecon(lu, anorm, norm=norm)
224 # Hermitian case 'hesv'
225 elif assume_a == 'her':
226 hecon, hesv, hesv_lw = get_lapack_funcs(('hecon', 'hesv',
227 'hesv_lwork'), (a1, b1))
228 lwork = _compute_lwork(hesv_lw, n, lower)
229 lu, ipvt, x, info = hesv(a1, b1, lwork=lwork,
230 lower=lower,
231 overwrite_a=overwrite_a,
232 overwrite_b=overwrite_b)
233 _solve_check(n, info)
234 rcond, info = hecon(lu, ipvt, anorm)
235 # Symmetric case 'sysv'
236 elif assume_a == 'sym':
237 sycon, sysv, sysv_lw = get_lapack_funcs(('sycon', 'sysv',
238 'sysv_lwork'), (a1, b1))
239 lwork = _compute_lwork(sysv_lw, n, lower)
240 lu, ipvt, x, info = sysv(a1, b1, lwork=lwork,
241 lower=lower,
242 overwrite_a=overwrite_a,
243 overwrite_b=overwrite_b)
244 _solve_check(n, info)
245 rcond, info = sycon(lu, ipvt, anorm)
246 # Positive definite case 'posv'
247 else:
248 pocon, posv = get_lapack_funcs(('pocon', 'posv'),
249 (a1, b1))
250 lu, x, info = posv(a1, b1, lower=lower,
251 overwrite_a=overwrite_a,
252 overwrite_b=overwrite_b)
253 _solve_check(n, info)
254 rcond, info = pocon(lu, anorm)
256 _solve_check(n, info, lamch, rcond)
258 if b_is_1D:
259 x = x.ravel()
261 return x
264def solve_triangular(a, b, trans=0, lower=False, unit_diagonal=False,
265 overwrite_b=False, check_finite=True):
266 """
267 Solve the equation `a x = b` for `x`, assuming a is a triangular matrix.
269 Parameters
270 ----------
271 a : (M, M) array_like
272 A triangular matrix
273 b : (M,) or (M, N) array_like
274 Right-hand side matrix in `a x = b`
275 lower : bool, optional
276 Use only data contained in the lower triangle of `a`.
277 Default is to use upper triangle.
278 trans : {0, 1, 2, 'N', 'T', 'C'}, optional
279 Type of system to solve:
281 ======== =========
282 trans system
283 ======== =========
284 0 or 'N' a x = b
285 1 or 'T' a^T x = b
286 2 or 'C' a^H x = b
287 ======== =========
288 unit_diagonal : bool, optional
289 If True, diagonal elements of `a` are assumed to be 1 and
290 will not be referenced.
291 overwrite_b : bool, optional
292 Allow overwriting data in `b` (may enhance performance)
293 check_finite : bool, optional
294 Whether to check that the input matrices contain only finite numbers.
295 Disabling may give a performance gain, but may result in problems
296 (crashes, non-termination) if the inputs do contain infinities or NaNs.
298 Returns
299 -------
300 x : (M,) or (M, N) ndarray
301 Solution to the system `a x = b`. Shape of return matches `b`.
303 Raises
304 ------
305 LinAlgError
306 If `a` is singular
308 Notes
309 -----
310 .. versionadded:: 0.9.0
312 Examples
313 --------
314 Solve the lower triangular system a x = b, where::
316 [3 0 0 0] [4]
317 a = [2 1 0 0] b = [2]
318 [1 0 1 0] [4]
319 [1 1 1 1] [2]
321 >>> import numpy as np
322 >>> from scipy.linalg import solve_triangular
323 >>> a = np.array([[3, 0, 0, 0], [2, 1, 0, 0], [1, 0, 1, 0], [1, 1, 1, 1]])
324 >>> b = np.array([4, 2, 4, 2])
325 >>> x = solve_triangular(a, b, lower=True)
326 >>> x
327 array([ 1.33333333, -0.66666667, 2.66666667, -1.33333333])
328 >>> a.dot(x) # Check the result
329 array([ 4., 2., 4., 2.])
331 """
333 a1 = _asarray_validated(a, check_finite=check_finite)
334 b1 = _asarray_validated(b, check_finite=check_finite)
335 if len(a1.shape) != 2 or a1.shape[0] != a1.shape[1]:
336 raise ValueError('expected square matrix')
337 if a1.shape[0] != b1.shape[0]:
338 raise ValueError(f'shapes of a {a1.shape} and b {b1.shape} are incompatible')
339 overwrite_b = overwrite_b or _datacopied(b1, b)
341 trans = {'N': 0, 'T': 1, 'C': 2}.get(trans, trans)
342 trtrs, = get_lapack_funcs(('trtrs',), (a1, b1))
343 if a1.flags.f_contiguous or trans == 2:
344 x, info = trtrs(a1, b1, overwrite_b=overwrite_b, lower=lower,
345 trans=trans, unitdiag=unit_diagonal)
346 else:
347 # transposed system is solved since trtrs expects Fortran ordering
348 x, info = trtrs(a1.T, b1, overwrite_b=overwrite_b, lower=not lower,
349 trans=not trans, unitdiag=unit_diagonal)
351 if info == 0:
352 return x
353 if info > 0:
354 raise LinAlgError("singular matrix: resolution failed at diagonal %d" %
355 (info-1))
356 raise ValueError('illegal value in %dth argument of internal trtrs' %
357 (-info))
360def solve_banded(l_and_u, ab, b, overwrite_ab=False, overwrite_b=False,
361 check_finite=True):
362 """
363 Solve the equation a x = b for x, assuming a is banded matrix.
365 The matrix a is stored in `ab` using the matrix diagonal ordered form::
367 ab[u + i - j, j] == a[i,j]
369 Example of `ab` (shape of a is (6,6), `u` =1, `l` =2)::
371 * a01 a12 a23 a34 a45
372 a00 a11 a22 a33 a44 a55
373 a10 a21 a32 a43 a54 *
374 a20 a31 a42 a53 * *
376 Parameters
377 ----------
378 (l, u) : (integer, integer)
379 Number of non-zero lower and upper diagonals
380 ab : (`l` + `u` + 1, M) array_like
381 Banded matrix
382 b : (M,) or (M, K) array_like
383 Right-hand side
384 overwrite_ab : bool, optional
385 Discard data in `ab` (may enhance performance)
386 overwrite_b : bool, optional
387 Discard data in `b` (may enhance performance)
388 check_finite : bool, optional
389 Whether to check that the input matrices contain only finite numbers.
390 Disabling may give a performance gain, but may result in problems
391 (crashes, non-termination) if the inputs do contain infinities or NaNs.
393 Returns
394 -------
395 x : (M,) or (M, K) ndarray
396 The solution to the system a x = b. Returned shape depends on the
397 shape of `b`.
399 Examples
400 --------
401 Solve the banded system a x = b, where::
403 [5 2 -1 0 0] [0]
404 [1 4 2 -1 0] [1]
405 a = [0 1 3 2 -1] b = [2]
406 [0 0 1 2 2] [2]
407 [0 0 0 1 1] [3]
409 There is one nonzero diagonal below the main diagonal (l = 1), and
410 two above (u = 2). The diagonal banded form of the matrix is::
412 [* * -1 -1 -1]
413 ab = [* 2 2 2 2]
414 [5 4 3 2 1]
415 [1 1 1 1 *]
417 >>> import numpy as np
418 >>> from scipy.linalg import solve_banded
419 >>> ab = np.array([[0, 0, -1, -1, -1],
420 ... [0, 2, 2, 2, 2],
421 ... [5, 4, 3, 2, 1],
422 ... [1, 1, 1, 1, 0]])
423 >>> b = np.array([0, 1, 2, 2, 3])
424 >>> x = solve_banded((1, 2), ab, b)
425 >>> x
426 array([-2.37288136, 3.93220339, -4. , 4.3559322 , -1.3559322 ])
428 """
430 a1 = _asarray_validated(ab, check_finite=check_finite, as_inexact=True)
431 b1 = _asarray_validated(b, check_finite=check_finite, as_inexact=True)
432 # Validate shapes.
433 if a1.shape[-1] != b1.shape[0]:
434 raise ValueError("shapes of ab and b are not compatible.")
435 (nlower, nupper) = l_and_u
436 if nlower + nupper + 1 != a1.shape[0]:
437 raise ValueError("invalid values for the number of lower and upper "
438 "diagonals: l+u+1 (%d) does not equal ab.shape[0] "
439 "(%d)" % (nlower + nupper + 1, ab.shape[0]))
441 overwrite_b = overwrite_b or _datacopied(b1, b)
442 if a1.shape[-1] == 1:
443 b2 = np.array(b1, copy=(not overwrite_b))
444 b2 /= a1[1, 0]
445 return b2
446 if nlower == nupper == 1:
447 overwrite_ab = overwrite_ab or _datacopied(a1, ab)
448 gtsv, = get_lapack_funcs(('gtsv',), (a1, b1))
449 du = a1[0, 1:]
450 d = a1[1, :]
451 dl = a1[2, :-1]
452 du2, d, du, x, info = gtsv(dl, d, du, b1, overwrite_ab, overwrite_ab,
453 overwrite_ab, overwrite_b)
454 else:
455 gbsv, = get_lapack_funcs(('gbsv',), (a1, b1))
456 a2 = np.zeros((2*nlower + nupper + 1, a1.shape[1]), dtype=gbsv.dtype)
457 a2[nlower:, :] = a1
458 lu, piv, x, info = gbsv(nlower, nupper, a2, b1, overwrite_ab=True,
459 overwrite_b=overwrite_b)
460 if info == 0:
461 return x
462 if info > 0:
463 raise LinAlgError("singular matrix")
464 raise ValueError('illegal value in %d-th argument of internal '
465 'gbsv/gtsv' % -info)
468def solveh_banded(ab, b, overwrite_ab=False, overwrite_b=False, lower=False,
469 check_finite=True):
470 """
471 Solve equation a x = b. a is Hermitian positive-definite banded matrix.
473 Uses Thomas' Algorithm, which is more efficient than standard LU
474 factorization, but should only be used for Hermitian positive-definite
475 matrices.
477 The matrix ``a`` is stored in `ab` either in lower diagonal or upper
478 diagonal ordered form:
480 ab[u + i - j, j] == a[i,j] (if upper form; i <= j)
481 ab[ i - j, j] == a[i,j] (if lower form; i >= j)
483 Example of `ab` (shape of ``a`` is (6, 6), number of upper diagonals,
484 ``u`` =2)::
486 upper form:
487 * * a02 a13 a24 a35
488 * a01 a12 a23 a34 a45
489 a00 a11 a22 a33 a44 a55
491 lower form:
492 a00 a11 a22 a33 a44 a55
493 a10 a21 a32 a43 a54 *
494 a20 a31 a42 a53 * *
496 Cells marked with * are not used.
498 Parameters
499 ----------
500 ab : (``u`` + 1, M) array_like
501 Banded matrix
502 b : (M,) or (M, K) array_like
503 Right-hand side
504 overwrite_ab : bool, optional
505 Discard data in `ab` (may enhance performance)
506 overwrite_b : bool, optional
507 Discard data in `b` (may enhance performance)
508 lower : bool, optional
509 Is the matrix in the lower form. (Default is upper form)
510 check_finite : bool, optional
511 Whether to check that the input matrices contain only finite numbers.
512 Disabling may give a performance gain, but may result in problems
513 (crashes, non-termination) if the inputs do contain infinities or NaNs.
515 Returns
516 -------
517 x : (M,) or (M, K) ndarray
518 The solution to the system ``a x = b``. Shape of return matches shape
519 of `b`.
521 Notes
522 -----
523 In the case of a non-positive definite matrix ``a``, the solver
524 `solve_banded` may be used.
526 Examples
527 --------
528 Solve the banded system ``A x = b``, where::
530 [ 4 2 -1 0 0 0] [1]
531 [ 2 5 2 -1 0 0] [2]
532 A = [-1 2 6 2 -1 0] b = [2]
533 [ 0 -1 2 7 2 -1] [3]
534 [ 0 0 -1 2 8 2] [3]
535 [ 0 0 0 -1 2 9] [3]
537 >>> import numpy as np
538 >>> from scipy.linalg import solveh_banded
540 ``ab`` contains the main diagonal and the nonzero diagonals below the
541 main diagonal. That is, we use the lower form:
543 >>> ab = np.array([[ 4, 5, 6, 7, 8, 9],
544 ... [ 2, 2, 2, 2, 2, 0],
545 ... [-1, -1, -1, -1, 0, 0]])
546 >>> b = np.array([1, 2, 2, 3, 3, 3])
547 >>> x = solveh_banded(ab, b, lower=True)
548 >>> x
549 array([ 0.03431373, 0.45938375, 0.05602241, 0.47759104, 0.17577031,
550 0.34733894])
553 Solve the Hermitian banded system ``H x = b``, where::
555 [ 8 2-1j 0 0 ] [ 1 ]
556 H = [2+1j 5 1j 0 ] b = [1+1j]
557 [ 0 -1j 9 -2-1j] [1-2j]
558 [ 0 0 -2+1j 6 ] [ 0 ]
560 In this example, we put the upper diagonals in the array ``hb``:
562 >>> hb = np.array([[0, 2-1j, 1j, -2-1j],
563 ... [8, 5, 9, 6 ]])
564 >>> b = np.array([1, 1+1j, 1-2j, 0])
565 >>> x = solveh_banded(hb, b)
566 >>> x
567 array([ 0.07318536-0.02939412j, 0.11877624+0.17696461j,
568 0.10077984-0.23035393j, -0.00479904-0.09358128j])
570 """
571 a1 = _asarray_validated(ab, check_finite=check_finite)
572 b1 = _asarray_validated(b, check_finite=check_finite)
573 # Validate shapes.
574 if a1.shape[-1] != b1.shape[0]:
575 raise ValueError("shapes of ab and b are not compatible.")
577 overwrite_b = overwrite_b or _datacopied(b1, b)
578 overwrite_ab = overwrite_ab or _datacopied(a1, ab)
580 if a1.shape[0] == 2:
581 ptsv, = get_lapack_funcs(('ptsv',), (a1, b1))
582 if lower:
583 d = a1[0, :].real
584 e = a1[1, :-1]
585 else:
586 d = a1[1, :].real
587 e = a1[0, 1:].conj()
588 d, du, x, info = ptsv(d, e, b1, overwrite_ab, overwrite_ab,
589 overwrite_b)
590 else:
591 pbsv, = get_lapack_funcs(('pbsv',), (a1, b1))
592 c, x, info = pbsv(a1, b1, lower=lower, overwrite_ab=overwrite_ab,
593 overwrite_b=overwrite_b)
594 if info > 0:
595 raise LinAlgError("%dth leading minor not positive definite" % info)
596 if info < 0:
597 raise ValueError('illegal value in %dth argument of internal '
598 'pbsv' % -info)
599 return x
602def solve_toeplitz(c_or_cr, b, check_finite=True):
603 """Solve a Toeplitz system using Levinson Recursion
605 The Toeplitz matrix has constant diagonals, with c as its first column
606 and r as its first row. If r is not given, ``r == conjugate(c)`` is
607 assumed.
609 Parameters
610 ----------
611 c_or_cr : array_like or tuple of (array_like, array_like)
612 The vector ``c``, or a tuple of arrays (``c``, ``r``). Whatever the
613 actual shape of ``c``, it will be converted to a 1-D array. If not
614 supplied, ``r = conjugate(c)`` is assumed; in this case, if c[0] is
615 real, the Toeplitz matrix is Hermitian. r[0] is ignored; the first row
616 of the Toeplitz matrix is ``[c[0], r[1:]]``. Whatever the actual shape
617 of ``r``, it will be converted to a 1-D array.
618 b : (M,) or (M, K) array_like
619 Right-hand side in ``T x = b``.
620 check_finite : bool, optional
621 Whether to check that the input matrices contain only finite numbers.
622 Disabling may give a performance gain, but may result in problems
623 (result entirely NaNs) if the inputs do contain infinities or NaNs.
625 Returns
626 -------
627 x : (M,) or (M, K) ndarray
628 The solution to the system ``T x = b``. Shape of return matches shape
629 of `b`.
631 See Also
632 --------
633 toeplitz : Toeplitz matrix
635 Notes
636 -----
637 The solution is computed using Levinson-Durbin recursion, which is faster
638 than generic least-squares methods, but can be less numerically stable.
640 Examples
641 --------
642 Solve the Toeplitz system T x = b, where::
644 [ 1 -1 -2 -3] [1]
645 T = [ 3 1 -1 -2] b = [2]
646 [ 6 3 1 -1] [2]
647 [10 6 3 1] [5]
649 To specify the Toeplitz matrix, only the first column and the first
650 row are needed.
652 >>> import numpy as np
653 >>> c = np.array([1, 3, 6, 10]) # First column of T
654 >>> r = np.array([1, -1, -2, -3]) # First row of T
655 >>> b = np.array([1, 2, 2, 5])
657 >>> from scipy.linalg import solve_toeplitz, toeplitz
658 >>> x = solve_toeplitz((c, r), b)
659 >>> x
660 array([ 1.66666667, -1. , -2.66666667, 2.33333333])
662 Check the result by creating the full Toeplitz matrix and
663 multiplying it by `x`. We should get `b`.
665 >>> T = toeplitz(c, r)
666 >>> T.dot(x)
667 array([ 1., 2., 2., 5.])
669 """
670 # If numerical stability of this algorithm is a problem, a future
671 # developer might consider implementing other O(N^2) Toeplitz solvers,
672 # such as GKO (https://www.jstor.org/stable/2153371) or Bareiss.
674 r, c, b, dtype, b_shape = _validate_args_for_toeplitz_ops(
675 c_or_cr, b, check_finite, keep_b_shape=True)
677 # Form a 1-D array of values to be used in the matrix, containing a
678 # reversed copy of r[1:], followed by c.
679 vals = np.concatenate((r[-1:0:-1], c))
680 if b is None:
681 raise ValueError('illegal value, `b` is a required argument')
683 if b.ndim == 1:
684 x, _ = levinson(vals, np.ascontiguousarray(b))
685 else:
686 x = np.column_stack([levinson(vals, np.ascontiguousarray(b[:, i]))[0]
687 for i in range(b.shape[1])])
688 x = x.reshape(*b_shape)
690 return x
693def _get_axis_len(aname, a, axis):
694 ax = axis
695 if ax < 0:
696 ax += a.ndim
697 if 0 <= ax < a.ndim:
698 return a.shape[ax]
699 raise ValueError(f"'{aname}axis' entry is out of bounds")
702def solve_circulant(c, b, singular='raise', tol=None,
703 caxis=-1, baxis=0, outaxis=0):
704 """Solve C x = b for x, where C is a circulant matrix.
706 `C` is the circulant matrix associated with the vector `c`.
708 The system is solved by doing division in Fourier space. The
709 calculation is::
711 x = ifft(fft(b) / fft(c))
713 where `fft` and `ifft` are the fast Fourier transform and its inverse,
714 respectively. For a large vector `c`, this is *much* faster than
715 solving the system with the full circulant matrix.
717 Parameters
718 ----------
719 c : array_like
720 The coefficients of the circulant matrix.
721 b : array_like
722 Right-hand side matrix in ``a x = b``.
723 singular : str, optional
724 This argument controls how a near singular circulant matrix is
725 handled. If `singular` is "raise" and the circulant matrix is
726 near singular, a `LinAlgError` is raised. If `singular` is
727 "lstsq", the least squares solution is returned. Default is "raise".
728 tol : float, optional
729 If any eigenvalue of the circulant matrix has an absolute value
730 that is less than or equal to `tol`, the matrix is considered to be
731 near singular. If not given, `tol` is set to::
733 tol = abs_eigs.max() * abs_eigs.size * np.finfo(np.float64).eps
735 where `abs_eigs` is the array of absolute values of the eigenvalues
736 of the circulant matrix.
737 caxis : int
738 When `c` has dimension greater than 1, it is viewed as a collection
739 of circulant vectors. In this case, `caxis` is the axis of `c` that
740 holds the vectors of circulant coefficients.
741 baxis : int
742 When `b` has dimension greater than 1, it is viewed as a collection
743 of vectors. In this case, `baxis` is the axis of `b` that holds the
744 right-hand side vectors.
745 outaxis : int
746 When `c` or `b` are multidimensional, the value returned by
747 `solve_circulant` is multidimensional. In this case, `outaxis` is
748 the axis of the result that holds the solution vectors.
750 Returns
751 -------
752 x : ndarray
753 Solution to the system ``C x = b``.
755 Raises
756 ------
757 LinAlgError
758 If the circulant matrix associated with `c` is near singular.
760 See Also
761 --------
762 circulant : circulant matrix
764 Notes
765 -----
766 For a 1-D vector `c` with length `m`, and an array `b`
767 with shape ``(m, ...)``,
769 solve_circulant(c, b)
771 returns the same result as
773 solve(circulant(c), b)
775 where `solve` and `circulant` are from `scipy.linalg`.
777 .. versionadded:: 0.16.0
779 Examples
780 --------
781 >>> import numpy as np
782 >>> from scipy.linalg import solve_circulant, solve, circulant, lstsq
784 >>> c = np.array([2, 2, 4])
785 >>> b = np.array([1, 2, 3])
786 >>> solve_circulant(c, b)
787 array([ 0.75, -0.25, 0.25])
789 Compare that result to solving the system with `scipy.linalg.solve`:
791 >>> solve(circulant(c), b)
792 array([ 0.75, -0.25, 0.25])
794 A singular example:
796 >>> c = np.array([1, 1, 0, 0])
797 >>> b = np.array([1, 2, 3, 4])
799 Calling ``solve_circulant(c, b)`` will raise a `LinAlgError`. For the
800 least square solution, use the option ``singular='lstsq'``:
802 >>> solve_circulant(c, b, singular='lstsq')
803 array([ 0.25, 1.25, 2.25, 1.25])
805 Compare to `scipy.linalg.lstsq`:
807 >>> x, resid, rnk, s = lstsq(circulant(c), b)
808 >>> x
809 array([ 0.25, 1.25, 2.25, 1.25])
811 A broadcasting example:
813 Suppose we have the vectors of two circulant matrices stored in an array
814 with shape (2, 5), and three `b` vectors stored in an array with shape
815 (3, 5). For example,
817 >>> c = np.array([[1.5, 2, 3, 0, 0], [1, 1, 4, 3, 2]])
818 >>> b = np.arange(15).reshape(-1, 5)
820 We want to solve all combinations of circulant matrices and `b` vectors,
821 with the result stored in an array with shape (2, 3, 5). When we
822 disregard the axes of `c` and `b` that hold the vectors of coefficients,
823 the shapes of the collections are (2,) and (3,), respectively, which are
824 not compatible for broadcasting. To have a broadcast result with shape
825 (2, 3), we add a trivial dimension to `c`: ``c[:, np.newaxis, :]`` has
826 shape (2, 1, 5). The last dimension holds the coefficients of the
827 circulant matrices, so when we call `solve_circulant`, we can use the
828 default ``caxis=-1``. The coefficients of the `b` vectors are in the last
829 dimension of the array `b`, so we use ``baxis=-1``. If we use the
830 default `outaxis`, the result will have shape (5, 2, 3), so we'll use
831 ``outaxis=-1`` to put the solution vectors in the last dimension.
833 >>> x = solve_circulant(c[:, np.newaxis, :], b, baxis=-1, outaxis=-1)
834 >>> x.shape
835 (2, 3, 5)
836 >>> np.set_printoptions(precision=3) # For compact output of numbers.
837 >>> x
838 array([[[-0.118, 0.22 , 1.277, -0.142, 0.302],
839 [ 0.651, 0.989, 2.046, 0.627, 1.072],
840 [ 1.42 , 1.758, 2.816, 1.396, 1.841]],
841 [[ 0.401, 0.304, 0.694, -0.867, 0.377],
842 [ 0.856, 0.758, 1.149, -0.412, 0.831],
843 [ 1.31 , 1.213, 1.603, 0.042, 1.286]]])
845 Check by solving one pair of `c` and `b` vectors (cf. ``x[1, 1, :]``):
847 >>> solve_circulant(c[1], b[1, :])
848 array([ 0.856, 0.758, 1.149, -0.412, 0.831])
850 """
851 c = np.atleast_1d(c)
852 nc = _get_axis_len("c", c, caxis)
853 b = np.atleast_1d(b)
854 nb = _get_axis_len("b", b, baxis)
855 if nc != nb:
856 raise ValueError(f'Shapes of c {c.shape} and b {b.shape} are incompatible')
858 fc = np.fft.fft(np.moveaxis(c, caxis, -1), axis=-1)
859 abs_fc = np.abs(fc)
860 if tol is None:
861 # This is the same tolerance as used in np.linalg.matrix_rank.
862 tol = abs_fc.max(axis=-1) * nc * np.finfo(np.float64).eps
863 if tol.shape != ():
864 tol.shape = tol.shape + (1,)
865 else:
866 tol = np.atleast_1d(tol)
868 near_zeros = abs_fc <= tol
869 is_near_singular = np.any(near_zeros)
870 if is_near_singular:
871 if singular == 'raise':
872 raise LinAlgError("near singular circulant matrix.")
873 else:
874 # Replace the small values with 1 to avoid errors in the
875 # division fb/fc below.
876 fc[near_zeros] = 1
878 fb = np.fft.fft(np.moveaxis(b, baxis, -1), axis=-1)
880 q = fb / fc
882 if is_near_singular:
883 # `near_zeros` is a boolean array, same shape as `c`, that is
884 # True where `fc` is (near) zero. `q` is the broadcasted result
885 # of fb / fc, so to set the values of `q` to 0 where `fc` is near
886 # zero, we use a mask that is the broadcast result of an array
887 # of True values shaped like `b` with `near_zeros`.
888 mask = np.ones_like(b, dtype=bool) & near_zeros
889 q[mask] = 0
891 x = np.fft.ifft(q, axis=-1)
892 if not (np.iscomplexobj(c) or np.iscomplexobj(b)):
893 x = x.real
894 if outaxis != -1:
895 x = np.moveaxis(x, -1, outaxis)
896 return x
899# matrix inversion
900def inv(a, overwrite_a=False, check_finite=True):
901 """
902 Compute the inverse of a matrix.
904 Parameters
905 ----------
906 a : array_like
907 Square matrix to be inverted.
908 overwrite_a : bool, optional
909 Discard data in `a` (may improve performance). Default is False.
910 check_finite : bool, optional
911 Whether to check that the input matrix contains only finite numbers.
912 Disabling may give a performance gain, but may result in problems
913 (crashes, non-termination) if the inputs do contain infinities or NaNs.
915 Returns
916 -------
917 ainv : ndarray
918 Inverse of the matrix `a`.
920 Raises
921 ------
922 LinAlgError
923 If `a` is singular.
924 ValueError
925 If `a` is not square, or not 2D.
927 Examples
928 --------
929 >>> import numpy as np
930 >>> from scipy import linalg
931 >>> a = np.array([[1., 2.], [3., 4.]])
932 >>> linalg.inv(a)
933 array([[-2. , 1. ],
934 [ 1.5, -0.5]])
935 >>> np.dot(a, linalg.inv(a))
936 array([[ 1., 0.],
937 [ 0., 1.]])
939 """
940 a1 = _asarray_validated(a, check_finite=check_finite)
941 if len(a1.shape) != 2 or a1.shape[0] != a1.shape[1]:
942 raise ValueError('expected square matrix')
943 overwrite_a = overwrite_a or _datacopied(a1, a)
944 getrf, getri, getri_lwork = get_lapack_funcs(('getrf', 'getri',
945 'getri_lwork'),
946 (a1,))
947 lu, piv, info = getrf(a1, overwrite_a=overwrite_a)
948 if info == 0:
949 lwork = _compute_lwork(getri_lwork, a1.shape[0])
951 # XXX: the following line fixes curious SEGFAULT when
952 # benchmarking 500x500 matrix inverse. This seems to
953 # be a bug in LAPACK ?getri routine because if lwork is
954 # minimal (when using lwork[0] instead of lwork[1]) then
955 # all tests pass. Further investigation is required if
956 # more such SEGFAULTs occur.
957 lwork = int(1.01 * lwork)
958 inv_a, info = getri(lu, piv, lwork=lwork, overwrite_lu=1)
959 if info > 0:
960 raise LinAlgError("singular matrix")
961 if info < 0:
962 raise ValueError('illegal value in %d-th argument of internal '
963 'getrf|getri' % -info)
964 return inv_a
967# Determinant
969def det(a, overwrite_a=False, check_finite=True):
970 """
971 Compute the determinant of a matrix
973 The determinant is a scalar that is a function of the associated square
974 matrix coefficients. The determinant value is zero for singular matrices.
976 Parameters
977 ----------
978 a : (..., M, M) array_like
979 Input array to compute determinants for.
980 overwrite_a : bool, optional
981 Allow overwriting data in a (may enhance performance).
982 check_finite : bool, optional
983 Whether to check that the input matrix contains only finite numbers.
984 Disabling may give a performance gain, but may result in problems
985 (crashes, non-termination) if the inputs do contain infinities or NaNs.
987 Returns
988 -------
989 det : (...) float or complex
990 Determinant of `a`. For stacked arrays, a scalar is returned for each
991 (m, m) slice in the last two dimensions of the input. For example, an
992 input of shape (p, q, m, m) will produce a result of shape (p, q). If
993 all dimensions are 1 a scalar is returned regardless of ndim.
995 Notes
996 -----
997 The determinant is computed by performing an LU factorization of the
998 input with LAPACK routine 'getrf', and then calculating the product of
999 diagonal entries of the U factor.
1001 Even the input array is single precision (float32 or complex64), the result
1002 will be returned in double precision (float64 or complex128) to prevent
1003 overflows.
1005 Examples
1006 --------
1007 >>> import numpy as np
1008 >>> from scipy import linalg
1009 >>> a = np.array([[1,2,3], [4,5,6], [7,8,9]]) # A singular matrix
1010 >>> linalg.det(a)
1011 0.0
1012 >>> b = np.array([[0,2,3], [4,5,6], [7,8,9]])
1013 >>> linalg.det(b)
1014 3.0
1015 >>> # An array with the shape (3, 2, 2, 2)
1016 >>> c = np.array([[[[1., 2.], [3., 4.]],
1017 ... [[5., 6.], [7., 8.]]],
1018 ... [[[9., 10.], [11., 12.]],
1019 ... [[13., 14.], [15., 16.]]],
1020 ... [[[17., 18.], [19., 20.]],
1021 ... [[21., 22.], [23., 24.]]]])
1022 >>> linalg.det(c) # The resulting shape is (3, 2)
1023 array([[-2., -2.],
1024 [-2., -2.],
1025 [-2., -2.]])
1026 >>> linalg.det(c[0, 0]) # Confirm the (0, 0) slice, [[1, 2], [3, 4]]
1027 -2.0
1028 """
1029 # The goal is to end up with a writable contiguous array to pass to Cython
1031 # First we check and make arrays.
1032 a1 = np.asarray_chkfinite(a) if check_finite else np.asarray(a)
1033 if a1.ndim < 2:
1034 raise ValueError('The input array must be at least two-dimensional.')
1035 if a1.shape[-1] != a1.shape[-2]:
1036 raise ValueError('Last 2 dimensions of the array must be square'
1037 f' but received shape {a1.shape}.')
1039 # Also check if dtype is LAPACK compatible
1040 if a1.dtype.char not in 'fdFD':
1041 dtype_char = lapack_cast_dict[a1.dtype.char]
1042 if not dtype_char: # No casting possible
1043 raise TypeError(f'The dtype "{a1.dtype.name}" cannot be cast '
1044 'to float(32, 64) or complex(64, 128).')
1046 a1 = a1.astype(dtype_char[0]) # makes a copy, free to scratch
1047 overwrite_a = True
1049 # Empty array has determinant 1 because math.
1050 if min(*a1.shape) == 0:
1051 if a1.ndim == 2:
1052 return np.float64(1.)
1053 else:
1054 return np.ones(shape=a1.shape[:-2], dtype=np.float64)
1056 # Scalar case
1057 if a1.shape[-2:] == (1, 1):
1058 # Either ndarray with spurious singletons or a single element
1059 if max(*a1.shape) > 1:
1060 temp = np.squeeze(a1)
1061 if a1.dtype.char in 'dD':
1062 return temp
1063 else:
1064 return (temp.astype('d') if a1.dtype.char == 'f' else
1065 temp.astype('D'))
1066 else:
1067 return (np.float64(a1.item()) if a1.dtype.char in 'fd' else
1068 np.complex128(a1.item()))
1070 # Then check overwrite permission
1071 if not _datacopied(a1, a): # "a" still alive through "a1"
1072 if not overwrite_a:
1073 # Data belongs to "a" so make a copy
1074 a1 = a1.copy(order='C')
1075 # else: Do nothing we'll use "a" if possible
1076 # else: a1 has its own data thus free to scratch
1078 # Then layout checks, might happen that overwrite is allowed but original
1079 # array was read-only or non-C-contiguous.
1080 if not (a1.flags['C_CONTIGUOUS'] and a1.flags['WRITEABLE']):
1081 a1 = a1.copy(order='C')
1083 if a1.ndim == 2:
1084 det = find_det_from_lu(a1)
1085 # Convert float, complex to to NumPy scalars
1086 return (np.float64(det) if np.isrealobj(det) else np.complex128(det))
1088 # loop over the stacked array, and avoid overflows for single precision
1089 # Cf. np.linalg.det(np.diag([1e+38, 1e+38]).astype(np.float32))
1090 dtype_char = a1.dtype.char
1091 if dtype_char in 'fF':
1092 dtype_char = 'd' if dtype_char.islower() else 'D'
1094 det = np.empty(a1.shape[:-2], dtype=dtype_char)
1095 for ind in product(*[range(x) for x in a1.shape[:-2]]):
1096 det[ind] = find_det_from_lu(a1[ind])
1097 return det
1100# Linear Least Squares
1101def lstsq(a, b, cond=None, overwrite_a=False, overwrite_b=False,
1102 check_finite=True, lapack_driver=None):
1103 """
1104 Compute least-squares solution to equation Ax = b.
1106 Compute a vector x such that the 2-norm ``|b - A x|`` is minimized.
1108 Parameters
1109 ----------
1110 a : (M, N) array_like
1111 Left-hand side array
1112 b : (M,) or (M, K) array_like
1113 Right hand side array
1114 cond : float, optional
1115 Cutoff for 'small' singular values; used to determine effective
1116 rank of a. Singular values smaller than
1117 ``cond * largest_singular_value`` are considered zero.
1118 overwrite_a : bool, optional
1119 Discard data in `a` (may enhance performance). Default is False.
1120 overwrite_b : bool, optional
1121 Discard data in `b` (may enhance performance). Default is False.
1122 check_finite : bool, optional
1123 Whether to check that the input matrices contain only finite numbers.
1124 Disabling may give a performance gain, but may result in problems
1125 (crashes, non-termination) if the inputs do contain infinities or NaNs.
1126 lapack_driver : str, optional
1127 Which LAPACK driver is used to solve the least-squares problem.
1128 Options are ``'gelsd'``, ``'gelsy'``, ``'gelss'``. Default
1129 (``'gelsd'``) is a good choice. However, ``'gelsy'`` can be slightly
1130 faster on many problems. ``'gelss'`` was used historically. It is
1131 generally slow but uses less memory.
1133 .. versionadded:: 0.17.0
1135 Returns
1136 -------
1137 x : (N,) or (N, K) ndarray
1138 Least-squares solution.
1139 residues : (K,) ndarray or float
1140 Square of the 2-norm for each column in ``b - a x``, if ``M > N`` and
1141 ``ndim(A) == n`` (returns a scalar if ``b`` is 1-D). Otherwise a
1142 (0,)-shaped array is returned.
1143 rank : int
1144 Effective rank of `a`.
1145 s : (min(M, N),) ndarray or None
1146 Singular values of `a`. The condition number of ``a`` is
1147 ``s[0] / s[-1]``.
1149 Raises
1150 ------
1151 LinAlgError
1152 If computation does not converge.
1154 ValueError
1155 When parameters are not compatible.
1157 See Also
1158 --------
1159 scipy.optimize.nnls : linear least squares with non-negativity constraint
1161 Notes
1162 -----
1163 When ``'gelsy'`` is used as a driver, `residues` is set to a (0,)-shaped
1164 array and `s` is always ``None``.
1166 Examples
1167 --------
1168 >>> import numpy as np
1169 >>> from scipy.linalg import lstsq
1170 >>> import matplotlib.pyplot as plt
1172 Suppose we have the following data:
1174 >>> x = np.array([1, 2.5, 3.5, 4, 5, 7, 8.5])
1175 >>> y = np.array([0.3, 1.1, 1.5, 2.0, 3.2, 6.6, 8.6])
1177 We want to fit a quadratic polynomial of the form ``y = a + b*x**2``
1178 to this data. We first form the "design matrix" M, with a constant
1179 column of 1s and a column containing ``x**2``:
1181 >>> M = x[:, np.newaxis]**[0, 2]
1182 >>> M
1183 array([[ 1. , 1. ],
1184 [ 1. , 6.25],
1185 [ 1. , 12.25],
1186 [ 1. , 16. ],
1187 [ 1. , 25. ],
1188 [ 1. , 49. ],
1189 [ 1. , 72.25]])
1191 We want to find the least-squares solution to ``M.dot(p) = y``,
1192 where ``p`` is a vector with length 2 that holds the parameters
1193 ``a`` and ``b``.
1195 >>> p, res, rnk, s = lstsq(M, y)
1196 >>> p
1197 array([ 0.20925829, 0.12013861])
1199 Plot the data and the fitted curve.
1201 >>> plt.plot(x, y, 'o', label='data')
1202 >>> xx = np.linspace(0, 9, 101)
1203 >>> yy = p[0] + p[1]*xx**2
1204 >>> plt.plot(xx, yy, label='least squares fit, $y = a + bx^2$')
1205 >>> plt.xlabel('x')
1206 >>> plt.ylabel('y')
1207 >>> plt.legend(framealpha=1, shadow=True)
1208 >>> plt.grid(alpha=0.25)
1209 >>> plt.show()
1211 """
1212 a1 = _asarray_validated(a, check_finite=check_finite)
1213 b1 = _asarray_validated(b, check_finite=check_finite)
1214 if len(a1.shape) != 2:
1215 raise ValueError('Input array a should be 2D')
1216 m, n = a1.shape
1217 if len(b1.shape) == 2:
1218 nrhs = b1.shape[1]
1219 else:
1220 nrhs = 1
1221 if m != b1.shape[0]:
1222 raise ValueError('Shape mismatch: a and b should have the same number'
1223 f' of rows ({m} != {b1.shape[0]}).')
1224 if m == 0 or n == 0: # Zero-sized problem, confuses LAPACK
1225 x = np.zeros((n,) + b1.shape[1:], dtype=np.common_type(a1, b1))
1226 if n == 0:
1227 residues = np.linalg.norm(b1, axis=0)**2
1228 else:
1229 residues = np.empty((0,))
1230 return x, residues, 0, np.empty((0,))
1232 driver = lapack_driver
1233 if driver is None:
1234 driver = lstsq.default_lapack_driver
1235 if driver not in ('gelsd', 'gelsy', 'gelss'):
1236 raise ValueError('LAPACK driver "%s" is not found' % driver)
1238 lapack_func, lapack_lwork = get_lapack_funcs((driver,
1239 '%s_lwork' % driver),
1240 (a1, b1))
1241 real_data = True if (lapack_func.dtype.kind == 'f') else False
1243 if m < n:
1244 # need to extend b matrix as it will be filled with
1245 # a larger solution matrix
1246 if len(b1.shape) == 2:
1247 b2 = np.zeros((n, nrhs), dtype=lapack_func.dtype)
1248 b2[:m, :] = b1
1249 else:
1250 b2 = np.zeros(n, dtype=lapack_func.dtype)
1251 b2[:m] = b1
1252 b1 = b2
1254 overwrite_a = overwrite_a or _datacopied(a1, a)
1255 overwrite_b = overwrite_b or _datacopied(b1, b)
1257 if cond is None:
1258 cond = np.finfo(lapack_func.dtype).eps
1260 if driver in ('gelss', 'gelsd'):
1261 if driver == 'gelss':
1262 lwork = _compute_lwork(lapack_lwork, m, n, nrhs, cond)
1263 v, x, s, rank, work, info = lapack_func(a1, b1, cond, lwork,
1264 overwrite_a=overwrite_a,
1265 overwrite_b=overwrite_b)
1267 elif driver == 'gelsd':
1268 if real_data:
1269 lwork, iwork = _compute_lwork(lapack_lwork, m, n, nrhs, cond)
1270 x, s, rank, info = lapack_func(a1, b1, lwork,
1271 iwork, cond, False, False)
1272 else: # complex data
1273 lwork, rwork, iwork = _compute_lwork(lapack_lwork, m, n,
1274 nrhs, cond)
1275 x, s, rank, info = lapack_func(a1, b1, lwork, rwork, iwork,
1276 cond, False, False)
1277 if info > 0:
1278 raise LinAlgError("SVD did not converge in Linear Least Squares")
1279 if info < 0:
1280 raise ValueError('illegal value in %d-th argument of internal %s'
1281 % (-info, lapack_driver))
1282 resids = np.asarray([], dtype=x.dtype)
1283 if m > n:
1284 x1 = x[:n]
1285 if rank == n:
1286 resids = np.sum(np.abs(x[n:])**2, axis=0)
1287 x = x1
1288 return x, resids, rank, s
1290 elif driver == 'gelsy':
1291 lwork = _compute_lwork(lapack_lwork, m, n, nrhs, cond)
1292 jptv = np.zeros((a1.shape[1], 1), dtype=np.int32)
1293 v, x, j, rank, info = lapack_func(a1, b1, jptv, cond,
1294 lwork, False, False)
1295 if info < 0:
1296 raise ValueError("illegal value in %d-th argument of internal "
1297 "gelsy" % -info)
1298 if m > n:
1299 x1 = x[:n]
1300 x = x1
1301 return x, np.array([], x.dtype), rank, None
1304lstsq.default_lapack_driver = 'gelsd'
1307@_deprecate_positional_args(version="1.14")
1308def pinv(a, *, atol=None, rtol=None, return_rank=False, check_finite=True,
1309 cond=_NoValue, rcond=_NoValue):
1310 """
1311 Compute the (Moore-Penrose) pseudo-inverse of a matrix.
1313 Calculate a generalized inverse of a matrix using its
1314 singular-value decomposition ``U @ S @ V`` in the economy mode and picking
1315 up only the columns/rows that are associated with significant singular
1316 values.
1318 If ``s`` is the maximum singular value of ``a``, then the
1319 significance cut-off value is determined by ``atol + rtol * s``. Any
1320 singular value below this value is assumed insignificant.
1322 Parameters
1323 ----------
1324 a : (M, N) array_like
1325 Matrix to be pseudo-inverted.
1326 atol : float, optional
1327 Absolute threshold term, default value is 0.
1329 .. versionadded:: 1.7.0
1331 rtol : float, optional
1332 Relative threshold term, default value is ``max(M, N) * eps`` where
1333 ``eps`` is the machine precision value of the datatype of ``a``.
1335 .. versionadded:: 1.7.0
1337 return_rank : bool, optional
1338 If True, return the effective rank of the matrix.
1339 check_finite : bool, optional
1340 Whether to check that the input matrix contains only finite numbers.
1341 Disabling may give a performance gain, but may result in problems
1342 (crashes, non-termination) if the inputs do contain infinities or NaNs.
1343 cond, rcond : float, optional
1344 In older versions, these values were meant to be used as ``atol`` with
1345 ``rtol=0``. If both were given ``rcond`` overwrote ``cond`` and hence
1346 the code was not correct. Thus using these are strongly discouraged and
1347 the tolerances above are recommended instead. In fact, if provided,
1348 atol, rtol takes precedence over these keywords.
1350 .. deprecated:: 1.7.0
1351 Deprecated in favor of ``rtol`` and ``atol`` parameters above and
1352 will be removed in SciPy 1.14.0.
1354 .. versionchanged:: 1.3.0
1355 Previously the default cutoff value was just ``eps*f`` where ``f``
1356 was ``1e3`` for single precision and ``1e6`` for double precision.
1358 Returns
1359 -------
1360 B : (N, M) ndarray
1361 The pseudo-inverse of matrix `a`.
1362 rank : int
1363 The effective rank of the matrix. Returned if `return_rank` is True.
1365 Raises
1366 ------
1367 LinAlgError
1368 If SVD computation does not converge.
1370 See Also
1371 --------
1372 pinvh : Moore-Penrose pseudoinverse of a hermitian matrix.
1374 Notes
1375 -----
1376 If ``A`` is invertible then the Moore-Penrose pseudoinverse is exactly
1377 the inverse of ``A`` [1]_. If ``A`` is not invertible then the
1378 Moore-Penrose pseudoinverse computes the ``x`` solution to ``Ax = b`` such
1379 that ``||Ax - b||`` is minimized [1]_.
1381 References
1382 ----------
1383 .. [1] Penrose, R. (1956). On best approximate solutions of linear matrix
1384 equations. Mathematical Proceedings of the Cambridge Philosophical
1385 Society, 52(1), 17-19. doi:10.1017/S0305004100030929
1387 Examples
1388 --------
1390 Given an ``m x n`` matrix ``A`` and an ``n x m`` matrix ``B`` the four
1391 Moore-Penrose conditions are:
1393 1. ``ABA = A`` (``B`` is a generalized inverse of ``A``),
1394 2. ``BAB = B`` (``A`` is a generalized inverse of ``B``),
1395 3. ``(AB)* = AB`` (``AB`` is hermitian),
1396 4. ``(BA)* = BA`` (``BA`` is hermitian) [1]_.
1398 Here, ``A*`` denotes the conjugate transpose. The Moore-Penrose
1399 pseudoinverse is a unique ``B`` that satisfies all four of these
1400 conditions and exists for any ``A``. Note that, unlike the standard
1401 matrix inverse, ``A`` does not have to be a square matrix or have
1402 linearly independent columns/rows.
1404 As an example, we can calculate the Moore-Penrose pseudoinverse of a
1405 random non-square matrix and verify it satisfies the four conditions.
1407 >>> import numpy as np
1408 >>> from scipy import linalg
1409 >>> rng = np.random.default_rng()
1410 >>> A = rng.standard_normal((9, 6))
1411 >>> B = linalg.pinv(A)
1412 >>> np.allclose(A @ B @ A, A) # Condition 1
1413 True
1414 >>> np.allclose(B @ A @ B, B) # Condition 2
1415 True
1416 >>> np.allclose((A @ B).conj().T, A @ B) # Condition 3
1417 True
1418 >>> np.allclose((B @ A).conj().T, B @ A) # Condition 4
1419 True
1421 """
1422 a = _asarray_validated(a, check_finite=check_finite)
1423 u, s, vh = _decomp_svd.svd(a, full_matrices=False, check_finite=False)
1424 t = u.dtype.char.lower()
1425 maxS = np.max(s)
1427 if rcond is not _NoValue or cond is not _NoValue:
1428 warn('Use of the "cond" and "rcond" keywords are deprecated and '
1429 'will be removed in SciPy 1.14.0. Use "atol" and '
1430 '"rtol" keywords instead', DeprecationWarning, stacklevel=2)
1432 # backwards compatible only atol and rtol are both missing
1433 if ((rcond not in (_NoValue, None) or cond not in (_NoValue, None))
1434 and (atol is None) and (rtol is None)):
1435 atol = rcond if rcond not in (_NoValue, None) else cond
1436 rtol = 0.
1438 atol = 0. if atol is None else atol
1439 rtol = max(a.shape) * np.finfo(t).eps if (rtol is None) else rtol
1441 if (atol < 0.) or (rtol < 0.):
1442 raise ValueError("atol and rtol values must be positive.")
1444 val = atol + maxS * rtol
1445 rank = np.sum(s > val)
1447 u = u[:, :rank]
1448 u /= s[:rank]
1449 B = (u @ vh[:rank]).conj().T
1451 if return_rank:
1452 return B, rank
1453 else:
1454 return B
1457def pinvh(a, atol=None, rtol=None, lower=True, return_rank=False,
1458 check_finite=True):
1459 """
1460 Compute the (Moore-Penrose) pseudo-inverse of a Hermitian matrix.
1462 Calculate a generalized inverse of a complex Hermitian/real symmetric
1463 matrix using its eigenvalue decomposition and including all eigenvalues
1464 with 'large' absolute value.
1466 Parameters
1467 ----------
1468 a : (N, N) array_like
1469 Real symmetric or complex hermetian matrix to be pseudo-inverted
1471 atol : float, optional
1472 Absolute threshold term, default value is 0.
1474 .. versionadded:: 1.7.0
1476 rtol : float, optional
1477 Relative threshold term, default value is ``N * eps`` where
1478 ``eps`` is the machine precision value of the datatype of ``a``.
1480 .. versionadded:: 1.7.0
1482 lower : bool, optional
1483 Whether the pertinent array data is taken from the lower or upper
1484 triangle of `a`. (Default: lower)
1485 return_rank : bool, optional
1486 If True, return the effective rank of the matrix.
1487 check_finite : bool, optional
1488 Whether to check that the input matrix contains only finite numbers.
1489 Disabling may give a performance gain, but may result in problems
1490 (crashes, non-termination) if the inputs do contain infinities or NaNs.
1492 Returns
1493 -------
1494 B : (N, N) ndarray
1495 The pseudo-inverse of matrix `a`.
1496 rank : int
1497 The effective rank of the matrix. Returned if `return_rank` is True.
1499 Raises
1500 ------
1501 LinAlgError
1502 If eigenvalue algorithm does not converge.
1504 See Also
1505 --------
1506 pinv : Moore-Penrose pseudoinverse of a matrix.
1508 Examples
1509 --------
1511 For a more detailed example see `pinv`.
1513 >>> import numpy as np
1514 >>> from scipy.linalg import pinvh
1515 >>> rng = np.random.default_rng()
1516 >>> a = rng.standard_normal((9, 6))
1517 >>> a = np.dot(a, a.T)
1518 >>> B = pinvh(a)
1519 >>> np.allclose(a, a @ B @ a)
1520 True
1521 >>> np.allclose(B, B @ a @ B)
1522 True
1524 """
1525 a = _asarray_validated(a, check_finite=check_finite)
1526 s, u = _decomp.eigh(a, lower=lower, check_finite=False)
1527 t = u.dtype.char.lower()
1528 maxS = np.max(np.abs(s))
1530 atol = 0. if atol is None else atol
1531 rtol = max(a.shape) * np.finfo(t).eps if (rtol is None) else rtol
1533 if (atol < 0.) or (rtol < 0.):
1534 raise ValueError("atol and rtol values must be positive.")
1536 val = atol + maxS * rtol
1537 above_cutoff = (abs(s) > val)
1539 psigma_diag = 1.0 / s[above_cutoff]
1540 u = u[:, above_cutoff]
1542 B = (u * psigma_diag) @ u.conj().T
1544 if return_rank:
1545 return B, len(psigma_diag)
1546 else:
1547 return B
1550def matrix_balance(A, permute=True, scale=True, separate=False,
1551 overwrite_a=False):
1552 """
1553 Compute a diagonal similarity transformation for row/column balancing.
1555 The balancing tries to equalize the row and column 1-norms by applying
1556 a similarity transformation such that the magnitude variation of the
1557 matrix entries is reflected to the scaling matrices.
1559 Moreover, if enabled, the matrix is first permuted to isolate the upper
1560 triangular parts of the matrix and, again if scaling is also enabled,
1561 only the remaining subblocks are subjected to scaling.
1563 The balanced matrix satisfies the following equality
1565 .. math::
1567 B = T^{-1} A T
1569 The scaling coefficients are approximated to the nearest power of 2
1570 to avoid round-off errors.
1572 Parameters
1573 ----------
1574 A : (n, n) array_like
1575 Square data matrix for the balancing.
1576 permute : bool, optional
1577 The selector to define whether permutation of A is also performed
1578 prior to scaling.
1579 scale : bool, optional
1580 The selector to turn on and off the scaling. If False, the matrix
1581 will not be scaled.
1582 separate : bool, optional
1583 This switches from returning a full matrix of the transformation
1584 to a tuple of two separate 1-D permutation and scaling arrays.
1585 overwrite_a : bool, optional
1586 This is passed to xGEBAL directly. Essentially, overwrites the result
1587 to the data. It might increase the space efficiency. See LAPACK manual
1588 for details. This is False by default.
1590 Returns
1591 -------
1592 B : (n, n) ndarray
1593 Balanced matrix
1594 T : (n, n) ndarray
1595 A possibly permuted diagonal matrix whose nonzero entries are
1596 integer powers of 2 to avoid numerical truncation errors.
1597 scale, perm : (n,) ndarray
1598 If ``separate`` keyword is set to True then instead of the array
1599 ``T`` above, the scaling and the permutation vectors are given
1600 separately as a tuple without allocating the full array ``T``.
1602 Notes
1603 -----
1604 This algorithm is particularly useful for eigenvalue and matrix
1605 decompositions and in many cases it is already called by various
1606 LAPACK routines.
1608 The algorithm is based on the well-known technique of [1]_ and has
1609 been modified to account for special cases. See [2]_ for details
1610 which have been implemented since LAPACK v3.5.0. Before this version
1611 there are corner cases where balancing can actually worsen the
1612 conditioning. See [3]_ for such examples.
1614 The code is a wrapper around LAPACK's xGEBAL routine family for matrix
1615 balancing.
1617 .. versionadded:: 0.19.0
1619 References
1620 ----------
1621 .. [1] B.N. Parlett and C. Reinsch, "Balancing a Matrix for
1622 Calculation of Eigenvalues and Eigenvectors", Numerische Mathematik,
1623 Vol.13(4), 1969, :doi:`10.1007/BF02165404`
1624 .. [2] R. James, J. Langou, B.R. Lowery, "On matrix balancing and
1625 eigenvector computation", 2014, :arxiv:`1401.5766`
1626 .. [3] D.S. Watkins. A case where balancing is harmful.
1627 Electron. Trans. Numer. Anal, Vol.23, 2006.
1629 Examples
1630 --------
1631 >>> import numpy as np
1632 >>> from scipy import linalg
1633 >>> x = np.array([[1,2,0], [9,1,0.01], [1,2,10*np.pi]])
1635 >>> y, permscale = linalg.matrix_balance(x)
1636 >>> np.abs(x).sum(axis=0) / np.abs(x).sum(axis=1)
1637 array([ 3.66666667, 0.4995005 , 0.91312162])
1639 >>> np.abs(y).sum(axis=0) / np.abs(y).sum(axis=1)
1640 array([ 1.2 , 1.27041742, 0.92658316]) # may vary
1642 >>> permscale # only powers of 2 (0.5 == 2^(-1))
1643 array([[ 0.5, 0. , 0. ], # may vary
1644 [ 0. , 1. , 0. ],
1645 [ 0. , 0. , 1. ]])
1647 """
1649 A = np.atleast_2d(_asarray_validated(A, check_finite=True))
1651 if not np.equal(*A.shape):
1652 raise ValueError('The data matrix for balancing should be square.')
1654 gebal = get_lapack_funcs(('gebal'), (A,))
1655 B, lo, hi, ps, info = gebal(A, scale=scale, permute=permute,
1656 overwrite_a=overwrite_a)
1658 if info < 0:
1659 raise ValueError('xGEBAL exited with the internal error '
1660 f'"illegal value in argument number {-info}.". See '
1661 'LAPACK documentation for the xGEBAL error codes.')
1663 # Separate the permutations from the scalings and then convert to int
1664 scaling = np.ones_like(ps, dtype=float)
1665 scaling[lo:hi+1] = ps[lo:hi+1]
1667 # gebal uses 1-indexing
1668 ps = ps.astype(int, copy=False) - 1
1669 n = A.shape[0]
1670 perm = np.arange(n)
1672 # LAPACK permutes with the ordering n --> hi, then 0--> lo
1673 if hi < n:
1674 for ind, x in enumerate(ps[hi+1:][::-1], 1):
1675 if n-ind == x:
1676 continue
1677 perm[[x, n-ind]] = perm[[n-ind, x]]
1679 if lo > 0:
1680 for ind, x in enumerate(ps[:lo]):
1681 if ind == x:
1682 continue
1683 perm[[x, ind]] = perm[[ind, x]]
1685 if separate:
1686 return B, (scaling, perm)
1688 # get the inverse permutation
1689 iperm = np.empty_like(perm)
1690 iperm[perm] = np.arange(n)
1692 return B, np.diag(scaling)[iperm, :]
1695def _validate_args_for_toeplitz_ops(c_or_cr, b, check_finite, keep_b_shape,
1696 enforce_square=True):
1697 """Validate arguments and format inputs for toeplitz functions
1699 Parameters
1700 ----------
1701 c_or_cr : array_like or tuple of (array_like, array_like)
1702 The vector ``c``, or a tuple of arrays (``c``, ``r``). Whatever the
1703 actual shape of ``c``, it will be converted to a 1-D array. If not
1704 supplied, ``r = conjugate(c)`` is assumed; in this case, if c[0] is
1705 real, the Toeplitz matrix is Hermitian. r[0] is ignored; the first row
1706 of the Toeplitz matrix is ``[c[0], r[1:]]``. Whatever the actual shape
1707 of ``r``, it will be converted to a 1-D array.
1708 b : (M,) or (M, K) array_like
1709 Right-hand side in ``T x = b``.
1710 check_finite : bool
1711 Whether to check that the input matrices contain only finite numbers.
1712 Disabling may give a performance gain, but may result in problems
1713 (result entirely NaNs) if the inputs do contain infinities or NaNs.
1714 keep_b_shape : bool
1715 Whether to convert a (M,) dimensional b into a (M, 1) dimensional
1716 matrix.
1717 enforce_square : bool, optional
1718 If True (default), this verifies that the Toeplitz matrix is square.
1720 Returns
1721 -------
1722 r : array
1723 1d array corresponding to the first row of the Toeplitz matrix.
1724 c: array
1725 1d array corresponding to the first column of the Toeplitz matrix.
1726 b: array
1727 (M,), (M, 1) or (M, K) dimensional array, post validation,
1728 corresponding to ``b``.
1729 dtype: numpy datatype
1730 ``dtype`` stores the datatype of ``r``, ``c`` and ``b``. If any of
1731 ``r``, ``c`` or ``b`` are complex, ``dtype`` is ``np.complex128``,
1732 otherwise, it is ``np.float``.
1733 b_shape: tuple
1734 Shape of ``b`` after passing it through ``_asarray_validated``.
1736 """
1738 if isinstance(c_or_cr, tuple):
1739 c, r = c_or_cr
1740 c = _asarray_validated(c, check_finite=check_finite).ravel()
1741 r = _asarray_validated(r, check_finite=check_finite).ravel()
1742 else:
1743 c = _asarray_validated(c_or_cr, check_finite=check_finite).ravel()
1744 r = c.conjugate()
1746 if b is None:
1747 raise ValueError('`b` must be an array, not None.')
1749 b = _asarray_validated(b, check_finite=check_finite)
1750 b_shape = b.shape
1752 is_not_square = r.shape[0] != c.shape[0]
1753 if (enforce_square and is_not_square) or b.shape[0] != r.shape[0]:
1754 raise ValueError('Incompatible dimensions.')
1756 is_cmplx = np.iscomplexobj(r) or np.iscomplexobj(c) or np.iscomplexobj(b)
1757 dtype = np.complex128 if is_cmplx else np.float64
1758 r, c, b = (np.asarray(i, dtype=dtype) for i in (r, c, b))
1760 if b.ndim == 1 and not keep_b_shape:
1761 b = b.reshape(-1, 1)
1762 elif b.ndim != 1:
1763 b = b.reshape(b.shape[0], -1)
1765 return r, c, b, dtype, b_shape
1768def matmul_toeplitz(c_or_cr, x, check_finite=False, workers=None):
1769 """Efficient Toeplitz Matrix-Matrix Multiplication using FFT
1771 This function returns the matrix multiplication between a Toeplitz
1772 matrix and a dense matrix.
1774 The Toeplitz matrix has constant diagonals, with c as its first column
1775 and r as its first row. If r is not given, ``r == conjugate(c)`` is
1776 assumed.
1778 Parameters
1779 ----------
1780 c_or_cr : array_like or tuple of (array_like, array_like)
1781 The vector ``c``, or a tuple of arrays (``c``, ``r``). Whatever the
1782 actual shape of ``c``, it will be converted to a 1-D array. If not
1783 supplied, ``r = conjugate(c)`` is assumed; in this case, if c[0] is
1784 real, the Toeplitz matrix is Hermitian. r[0] is ignored; the first row
1785 of the Toeplitz matrix is ``[c[0], r[1:]]``. Whatever the actual shape
1786 of ``r``, it will be converted to a 1-D array.
1787 x : (M,) or (M, K) array_like
1788 Matrix with which to multiply.
1789 check_finite : bool, optional
1790 Whether to check that the input matrices contain only finite numbers.
1791 Disabling may give a performance gain, but may result in problems
1792 (result entirely NaNs) if the inputs do contain infinities or NaNs.
1793 workers : int, optional
1794 To pass to scipy.fft.fft and ifft. Maximum number of workers to use
1795 for parallel computation. If negative, the value wraps around from
1796 ``os.cpu_count()``. See scipy.fft.fft for more details.
1798 Returns
1799 -------
1800 T @ x : (M,) or (M, K) ndarray
1801 The result of the matrix multiplication ``T @ x``. Shape of return
1802 matches shape of `x`.
1804 See Also
1805 --------
1806 toeplitz : Toeplitz matrix
1807 solve_toeplitz : Solve a Toeplitz system using Levinson Recursion
1809 Notes
1810 -----
1811 The Toeplitz matrix is embedded in a circulant matrix and the FFT is used
1812 to efficiently calculate the matrix-matrix product.
1814 Because the computation is based on the FFT, integer inputs will
1815 result in floating point outputs. This is unlike NumPy's `matmul`,
1816 which preserves the data type of the input.
1818 This is partly based on the implementation that can be found in [1]_,
1819 licensed under the MIT license. More information about the method can be
1820 found in reference [2]_. References [3]_ and [4]_ have more reference
1821 implementations in Python.
1823 .. versionadded:: 1.6.0
1825 References
1826 ----------
1827 .. [1] Jacob R Gardner, Geoff Pleiss, David Bindel, Kilian
1828 Q Weinberger, Andrew Gordon Wilson, "GPyTorch: Blackbox Matrix-Matrix
1829 Gaussian Process Inference with GPU Acceleration" with contributions
1830 from Max Balandat and Ruihan Wu. Available online:
1831 https://github.com/cornellius-gp/gpytorch
1833 .. [2] J. Demmel, P. Koev, and X. Li, "A Brief Survey of Direct Linear
1834 Solvers". In Z. Bai, J. Demmel, J. Dongarra, A. Ruhe, and H. van der
1835 Vorst, editors. Templates for the Solution of Algebraic Eigenvalue
1836 Problems: A Practical Guide. SIAM, Philadelphia, 2000. Available at:
1837 http://www.netlib.org/utk/people/JackDongarra/etemplates/node384.html
1839 .. [3] R. Scheibler, E. Bezzam, I. Dokmanic, Pyroomacoustics: A Python
1840 package for audio room simulations and array processing algorithms,
1841 Proc. IEEE ICASSP, Calgary, CA, 2018.
1842 https://github.com/LCAV/pyroomacoustics/blob/pypi-release/
1843 pyroomacoustics/adaptive/util.py
1845 .. [4] Marano S, Edwards B, Ferrari G and Fah D (2017), "Fitting
1846 Earthquake Spectra: Colored Noise and Incomplete Data", Bulletin of
1847 the Seismological Society of America., January, 2017. Vol. 107(1),
1848 pp. 276-291.
1850 Examples
1851 --------
1852 Multiply the Toeplitz matrix T with matrix x::
1854 [ 1 -1 -2 -3] [1 10]
1855 T = [ 3 1 -1 -2] x = [2 11]
1856 [ 6 3 1 -1] [2 11]
1857 [10 6 3 1] [5 19]
1859 To specify the Toeplitz matrix, only the first column and the first
1860 row are needed.
1862 >>> import numpy as np
1863 >>> c = np.array([1, 3, 6, 10]) # First column of T
1864 >>> r = np.array([1, -1, -2, -3]) # First row of T
1865 >>> x = np.array([[1, 10], [2, 11], [2, 11], [5, 19]])
1867 >>> from scipy.linalg import toeplitz, matmul_toeplitz
1868 >>> matmul_toeplitz((c, r), x)
1869 array([[-20., -80.],
1870 [ -7., -8.],
1871 [ 9., 85.],
1872 [ 33., 218.]])
1874 Check the result by creating the full Toeplitz matrix and
1875 multiplying it by ``x``.
1877 >>> toeplitz(c, r) @ x
1878 array([[-20, -80],
1879 [ -7, -8],
1880 [ 9, 85],
1881 [ 33, 218]])
1883 The full matrix is never formed explicitly, so this routine
1884 is suitable for very large Toeplitz matrices.
1886 >>> n = 1000000
1887 >>> matmul_toeplitz([1] + [0]*(n-1), np.ones(n))
1888 array([1., 1., 1., ..., 1., 1., 1.])
1890 """
1892 from ..fft import fft, ifft, rfft, irfft
1894 r, c, x, dtype, x_shape = _validate_args_for_toeplitz_ops(
1895 c_or_cr, x, check_finite, keep_b_shape=False, enforce_square=False)
1896 n, m = x.shape
1898 T_nrows = len(c)
1899 T_ncols = len(r)
1900 p = T_nrows + T_ncols - 1 # equivalent to len(embedded_col)
1902 embedded_col = np.concatenate((c, r[-1:0:-1]))
1904 if np.iscomplexobj(embedded_col) or np.iscomplexobj(x):
1905 fft_mat = fft(embedded_col, axis=0, workers=workers).reshape(-1, 1)
1906 fft_x = fft(x, n=p, axis=0, workers=workers)
1908 mat_times_x = ifft(fft_mat*fft_x, axis=0,
1909 workers=workers)[:T_nrows, :]
1910 else:
1911 # Real inputs; using rfft is faster
1912 fft_mat = rfft(embedded_col, axis=0, workers=workers).reshape(-1, 1)
1913 fft_x = rfft(x, n=p, axis=0, workers=workers)
1915 mat_times_x = irfft(fft_mat*fft_x, axis=0,
1916 workers=workers, n=p)[:T_nrows, :]
1918 return_shape = (T_nrows,) if len(x_shape) == 1 else (T_nrows, m)
1919 return mat_times_x.reshape(*return_shape)