Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/numpy/linalg/_linalg.py: 20%

752 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-04-09 06:12 +0000

1"""Lite version of scipy.linalg. 

2 

3Notes 

4----- 

5This module is a lite version of the linalg.py module in SciPy which 

6contains high-level Python interface to the LAPACK library. The lite 

7version only accesses the following LAPACK functions: dgesv, zgesv, 

8dgeev, zgeev, dgesdd, zgesdd, dgelsd, zgelsd, dsyevd, zheevd, dgetrf, 

9zgetrf, dpotrf, zpotrf, dgeqrf, zgeqrf, zungqr, dorgqr. 

10""" 

11 

12__all__ = ['matrix_power', 'solve', 'tensorsolve', 'tensorinv', 'inv', 

13 'cholesky', 'eigvals', 'eigvalsh', 'pinv', 'slogdet', 'det', 

14 'svd', 'svdvals', 'eig', 'eigh', 'lstsq', 'norm', 'qr', 'cond', 

15 'matrix_rank', 'LinAlgError', 'multi_dot', 'trace', 'diagonal', 

16 'cross', 'outer', 'tensordot', 'matmul', 'matrix_transpose', 

17 'matrix_norm', 'vector_norm', 'vecdot'] 

18 

19import functools 

20import operator 

21import warnings 

22from typing import NamedTuple, Any 

23 

24from numpy._utils import set_module 

25from numpy._core import ( 

26 array, asarray, zeros, empty, empty_like, intc, single, double, 

27 csingle, cdouble, inexact, complexfloating, newaxis, all, inf, dot, 

28 add, multiply, sqrt, sum, isfinite, finfo, errstate, moveaxis, amin, 

29 amax, prod, abs, atleast_2d, intp, asanyarray, object_, matmul, 

30 swapaxes, divide, count_nonzero, isnan, sign, argsort, sort, 

31 reciprocal, overrides, diagonal as _core_diagonal, trace as _core_trace, 

32 cross as _core_cross, outer as _core_outer, tensordot as _core_tensordot, 

33 matmul as _core_matmul, matrix_transpose as _core_matrix_transpose, 

34 transpose as _core_transpose, vecdot as _core_vecdot, 

35) 

36from numpy._globals import _NoValue 

37from numpy.lib._twodim_base_impl import triu, eye 

38from numpy.lib.array_utils import normalize_axis_index, normalize_axis_tuple 

39from numpy.linalg import _umath_linalg 

40 

41from numpy._typing import NDArray 

42 

43class EigResult(NamedTuple): 

44 eigenvalues: NDArray[Any] 

45 eigenvectors: NDArray[Any] 

46 

47class EighResult(NamedTuple): 

48 eigenvalues: NDArray[Any] 

49 eigenvectors: NDArray[Any] 

50 

51class QRResult(NamedTuple): 

52 Q: NDArray[Any] 

53 R: NDArray[Any] 

54 

55class SlogdetResult(NamedTuple): 

56 sign: NDArray[Any] 

57 logabsdet: NDArray[Any] 

58 

59class SVDResult(NamedTuple): 

60 U: NDArray[Any] 

61 S: NDArray[Any] 

62 Vh: NDArray[Any] 

63 

64 

65array_function_dispatch = functools.partial( 

66 overrides.array_function_dispatch, module='numpy.linalg' 

67) 

68 

69 

70fortran_int = intc 

71 

72 

73@set_module('numpy.linalg') 

74class LinAlgError(ValueError): 

75 """ 

76 Generic Python-exception-derived object raised by linalg functions. 

77 

78 General purpose exception class, derived from Python's ValueError 

79 class, programmatically raised in linalg functions when a Linear 

80 Algebra-related condition would prevent further correct execution of the 

81 function. 

82 

83 Parameters 

84 ---------- 

85 None 

86 

87 Examples 

88 -------- 

89 >>> from numpy import linalg as LA 

90 >>> LA.inv(np.zeros((2,2))) 

91 Traceback (most recent call last): 

92 File "<stdin>", line 1, in <module> 

93 File "...linalg.py", line 350, 

94 in inv return wrap(solve(a, identity(a.shape[0], dtype=a.dtype))) 

95 File "...linalg.py", line 249, 

96 in solve 

97 raise LinAlgError('Singular matrix') 

98 numpy.linalg.LinAlgError: Singular matrix 

99 

100 """ 

101 

102 

103def _raise_linalgerror_singular(err, flag): 

104 raise LinAlgError("Singular matrix") 

105 

106def _raise_linalgerror_nonposdef(err, flag): 

107 raise LinAlgError("Matrix is not positive definite") 

108 

109def _raise_linalgerror_eigenvalues_nonconvergence(err, flag): 

110 raise LinAlgError("Eigenvalues did not converge") 

111 

112def _raise_linalgerror_svd_nonconvergence(err, flag): 

113 raise LinAlgError("SVD did not converge") 

114 

115def _raise_linalgerror_lstsq(err, flag): 

116 raise LinAlgError("SVD did not converge in Linear Least Squares") 

117 

118def _raise_linalgerror_qr(err, flag): 

119 raise LinAlgError("Incorrect argument found while performing " 

120 "QR factorization") 

121 

122 

123def _makearray(a): 

124 new = asarray(a) 

125 wrap = getattr(a, "__array_wrap__", new.__array_wrap__) 

126 return new, wrap 

127 

128def isComplexType(t): 

129 return issubclass(t, complexfloating) 

130 

131 

132_real_types_map = {single: single, 

133 double: double, 

134 csingle: single, 

135 cdouble: double} 

136 

137_complex_types_map = {single: csingle, 

138 double: cdouble, 

139 csingle: csingle, 

140 cdouble: cdouble} 

141 

142def _realType(t, default=double): 

143 return _real_types_map.get(t, default) 

144 

145def _complexType(t, default=cdouble): 

146 return _complex_types_map.get(t, default) 

147 

148def _commonType(*arrays): 

149 # in lite version, use higher precision (always double or cdouble) 

150 result_type = single 

151 is_complex = False 

152 for a in arrays: 

153 type_ = a.dtype.type 

154 if issubclass(type_, inexact): 

155 if isComplexType(type_): 

156 is_complex = True 

157 rt = _realType(type_, default=None) 

158 if rt is double: 

159 result_type = double 

160 elif rt is None: 

161 # unsupported inexact scalar 

162 raise TypeError("array type %s is unsupported in linalg" % 

163 (a.dtype.name,)) 

164 else: 

165 result_type = double 

166 if is_complex: 

167 result_type = _complex_types_map[result_type] 

168 return cdouble, result_type 

169 else: 

170 return double, result_type 

171 

172 

173def _to_native_byte_order(*arrays): 

174 ret = [] 

175 for arr in arrays: 

176 if arr.dtype.byteorder not in ('=', '|'): 

177 ret.append(asarray(arr, dtype=arr.dtype.newbyteorder('='))) 

178 else: 

179 ret.append(arr) 

180 if len(ret) == 1: 

181 return ret[0] 

182 else: 

183 return ret 

184 

185 

186def _assert_2d(*arrays): 

187 for a in arrays: 

188 if a.ndim != 2: 

189 raise LinAlgError('%d-dimensional array given. Array must be ' 

190 'two-dimensional' % a.ndim) 

191 

192def _assert_stacked_2d(*arrays): 

193 for a in arrays: 

194 if a.ndim < 2: 

195 raise LinAlgError('%d-dimensional array given. Array must be ' 

196 'at least two-dimensional' % a.ndim) 

197 

198def _assert_stacked_square(*arrays): 

199 for a in arrays: 

200 m, n = a.shape[-2:] 

201 if m != n: 

202 raise LinAlgError('Last 2 dimensions of the array must be square') 

203 

204def _assert_finite(*arrays): 

205 for a in arrays: 

206 if not isfinite(a).all(): 

207 raise LinAlgError("Array must not contain infs or NaNs") 

208 

209def _is_empty_2d(arr): 

210 # check size first for efficiency 

211 return arr.size == 0 and prod(arr.shape[-2:]) == 0 

212 

213 

214def transpose(a): 

215 """ 

216 Transpose each matrix in a stack of matrices. 

217 

218 Unlike np.transpose, this only swaps the last two axes, rather than all of 

219 them 

220 

221 Parameters 

222 ---------- 

223 a : (...,M,N) array_like 

224 

225 Returns 

226 ------- 

227 aT : (...,N,M) ndarray 

228 """ 

229 return swapaxes(a, -1, -2) 

230 

231# Linear equations 

232 

233def _tensorsolve_dispatcher(a, b, axes=None): 

234 return (a, b) 

235 

236 

237@array_function_dispatch(_tensorsolve_dispatcher) 

238def tensorsolve(a, b, axes=None): 

239 """ 

240 Solve the tensor equation ``a x = b`` for x. 

241 

242 It is assumed that all indices of `x` are summed over in the product, 

243 together with the rightmost indices of `a`, as is done in, for example, 

244 ``tensordot(a, x, axes=x.ndim)``. 

245 

246 Parameters 

247 ---------- 

248 a : array_like 

249 Coefficient tensor, of shape ``b.shape + Q``. `Q`, a tuple, equals 

250 the shape of that sub-tensor of `a` consisting of the appropriate 

251 number of its rightmost indices, and must be such that 

252 ``prod(Q) == prod(b.shape)`` (in which sense `a` is said to be 

253 'square'). 

254 b : array_like 

255 Right-hand tensor, which can be of any shape. 

256 axes : tuple of ints, optional 

257 Axes in `a` to reorder to the right, before inversion. 

258 If None (default), no reordering is done. 

259 

260 Returns 

261 ------- 

262 x : ndarray, shape Q 

263 

264 Raises 

265 ------ 

266 LinAlgError 

267 If `a` is singular or not 'square' (in the above sense). 

268 

269 See Also 

270 -------- 

271 numpy.tensordot, tensorinv, numpy.einsum 

272 

273 Examples 

274 -------- 

275 >>> a = np.eye(2*3*4) 

276 >>> a.shape = (2*3, 4, 2, 3, 4) 

277 >>> b = np.random.randn(2*3, 4) 

278 >>> x = np.linalg.tensorsolve(a, b) 

279 >>> x.shape 

280 (2, 3, 4) 

281 >>> np.allclose(np.tensordot(a, x, axes=3), b) 

282 True 

283 

284 """ 

285 a, wrap = _makearray(a) 

286 b = asarray(b) 

287 an = a.ndim 

288 

289 if axes is not None: 

290 allaxes = list(range(0, an)) 

291 for k in axes: 

292 allaxes.remove(k) 

293 allaxes.insert(an, k) 

294 a = a.transpose(allaxes) 

295 

296 oldshape = a.shape[-(an-b.ndim):] 

297 prod = 1 

298 for k in oldshape: 

299 prod *= k 

300 

301 if a.size != prod ** 2: 

302 raise LinAlgError( 

303 "Input arrays must satisfy the requirement \ 

304 prod(a.shape[b.ndim:]) == prod(a.shape[:b.ndim])" 

305 ) 

306 

307 a = a.reshape(prod, prod) 

308 b = b.ravel() 

309 res = wrap(solve(a, b)) 

310 res.shape = oldshape 

311 return res 

312 

313 

314def _solve_dispatcher(a, b): 

315 return (a, b) 

316 

317 

318@array_function_dispatch(_solve_dispatcher) 

319def solve(a, b): 

320 """ 

321 Solve a linear matrix equation, or system of linear scalar equations. 

322 

323 Computes the "exact" solution, `x`, of the well-determined, i.e., full 

324 rank, linear matrix equation `ax = b`. 

325 

326 Parameters 

327 ---------- 

328 a : (..., M, M) array_like 

329 Coefficient matrix. 

330 b : {(M,), (..., M, K)}, array_like 

331 Ordinate or "dependent variable" values. 

332 

333 Returns 

334 ------- 

335 x : {(..., M,), (..., M, K)} ndarray 

336 Solution to the system a x = b. Returned shape is (..., M) if b is 

337 shape (M,) and (..., M, K) if b is (..., M, K), where the "..." part is 

338 broadcasted between a and b. 

339 

340 Raises 

341 ------ 

342 LinAlgError 

343 If `a` is singular or not square. 

344 

345 See Also 

346 -------- 

347 scipy.linalg.solve : Similar function in SciPy. 

348 

349 Notes 

350 ----- 

351 

352 .. versionadded:: 1.8.0 

353 

354 Broadcasting rules apply, see the `numpy.linalg` documentation for 

355 details. 

356 

357 The solutions are computed using LAPACK routine ``_gesv``. 

358 

359 `a` must be square and of full-rank, i.e., all rows (or, equivalently, 

360 columns) must be linearly independent; if either is not true, use 

361 `lstsq` for the least-squares best "solution" of the 

362 system/equation. 

363 

364 .. versionchanged:: 2.0 

365 

366 The b array is only treated as a shape (M,) column vector if it is 

367 exactly 1-dimensional. In all other instances it is treated as a stack 

368 of (M, K) matrices. Previously b would be treated as a stack of (M,) 

369 vectors if b.ndim was equal to a.ndim - 1. 

370 

371 References 

372 ---------- 

373 .. [1] G. Strang, *Linear Algebra and Its Applications*, 2nd Ed., Orlando, 

374 FL, Academic Press, Inc., 1980, pg. 22. 

375 

376 Examples 

377 -------- 

378 Solve the system of equations: 

379 ``x0 + 2 * x1 = 1`` and 

380 ``3 * x0 + 5 * x1 = 2``: 

381 

382 >>> a = np.array([[1, 2], [3, 5]]) 

383 >>> b = np.array([1, 2]) 

384 >>> x = np.linalg.solve(a, b) 

385 >>> x 

386 array([-1., 1.]) 

387 

388 Check that the solution is correct: 

389 

390 >>> np.allclose(np.dot(a, x), b) 

391 True 

392 

393 """ 

394 a, _ = _makearray(a) 

395 _assert_stacked_2d(a) 

396 _assert_stacked_square(a) 

397 b, wrap = _makearray(b) 

398 t, result_t = _commonType(a, b) 

399 

400 # We use the b = (..., M,) logic, only if the number of extra dimensions 

401 # match exactly 

402 if b.ndim == 1: 

403 gufunc = _umath_linalg.solve1 

404 else: 

405 gufunc = _umath_linalg.solve 

406 

407 signature = 'DD->D' if isComplexType(t) else 'dd->d' 

408 with errstate(call=_raise_linalgerror_singular, invalid='call', 

409 over='ignore', divide='ignore', under='ignore'): 

410 r = gufunc(a, b, signature=signature) 

411 

412 return wrap(r.astype(result_t, copy=False)) 

413 

414 

415def _tensorinv_dispatcher(a, ind=None): 

416 return (a,) 

417 

418 

419@array_function_dispatch(_tensorinv_dispatcher) 

420def tensorinv(a, ind=2): 

421 """ 

422 Compute the 'inverse' of an N-dimensional array. 

423 

424 The result is an inverse for `a` relative to the tensordot operation 

425 ``tensordot(a, b, ind)``, i. e., up to floating-point accuracy, 

426 ``tensordot(tensorinv(a), a, ind)`` is the "identity" tensor for the 

427 tensordot operation. 

428 

429 Parameters 

430 ---------- 

431 a : array_like 

432 Tensor to 'invert'. Its shape must be 'square', i. e., 

433 ``prod(a.shape[:ind]) == prod(a.shape[ind:])``. 

434 ind : int, optional 

435 Number of first indices that are involved in the inverse sum. 

436 Must be a positive integer, default is 2. 

437 

438 Returns 

439 ------- 

440 b : ndarray 

441 `a`'s tensordot inverse, shape ``a.shape[ind:] + a.shape[:ind]``. 

442 

443 Raises 

444 ------ 

445 LinAlgError 

446 If `a` is singular or not 'square' (in the above sense). 

447 

448 See Also 

449 -------- 

450 numpy.tensordot, tensorsolve 

451 

452 Examples 

453 -------- 

454 >>> a = np.eye(4*6) 

455 >>> a.shape = (4, 6, 8, 3) 

456 >>> ainv = np.linalg.tensorinv(a, ind=2) 

457 >>> ainv.shape 

458 (8, 3, 4, 6) 

459 >>> b = np.random.randn(4, 6) 

460 >>> np.allclose(np.tensordot(ainv, b), np.linalg.tensorsolve(a, b)) 

461 True 

462 

463 >>> a = np.eye(4*6) 

464 >>> a.shape = (24, 8, 3) 

465 >>> ainv = np.linalg.tensorinv(a, ind=1) 

466 >>> ainv.shape 

467 (8, 3, 24) 

468 >>> b = np.random.randn(24) 

469 >>> np.allclose(np.tensordot(ainv, b, 1), np.linalg.tensorsolve(a, b)) 

470 True 

471 

472 """ 

473 a = asarray(a) 

474 oldshape = a.shape 

475 prod = 1 

476 if ind > 0: 

477 invshape = oldshape[ind:] + oldshape[:ind] 

478 for k in oldshape[ind:]: 

479 prod *= k 

480 else: 

481 raise ValueError("Invalid ind argument.") 

482 a = a.reshape(prod, -1) 

483 ia = inv(a) 

484 return ia.reshape(*invshape) 

485 

486 

487# Matrix inversion 

488 

489def _unary_dispatcher(a): 

490 return (a,) 

491 

492 

493@array_function_dispatch(_unary_dispatcher) 

494def inv(a): 

495 """ 

496 Compute the inverse of a matrix. 

497 

498 Given a square matrix `a`, return the matrix `ainv` satisfying 

499 ``a @ ainv = ainv @ a = eye(a.shape[0])``. 

500 

501 Parameters 

502 ---------- 

503 a : (..., M, M) array_like 

504 Matrix to be inverted. 

505 

506 Returns 

507 ------- 

508 ainv : (..., M, M) ndarray or matrix 

509 Inverse of the matrix `a`. 

510 

511 Raises 

512 ------ 

513 LinAlgError 

514 If `a` is not square or inversion fails. 

515 

516 See Also 

517 -------- 

518 scipy.linalg.inv : Similar function in SciPy. 

519 numpy.linalg.cond : Compute the condition number of a matrix. 

520 numpy.linalg.svd : Compute the singular value decomposition of a matrix. 

521 

522 Notes 

523 ----- 

524 

525 .. versionadded:: 1.8.0 

526 

527 Broadcasting rules apply, see the `numpy.linalg` documentation for 

528 details. 

529 

530 If `a` is detected to be singular, a `LinAlgError` is raised. If `a` is 

531 ill-conditioned, a `LinAlgError` may or may not be raised, and results may 

532 be inaccurate due to floating-point errors. 

533 

534 References 

535 ---------- 

536 .. [1] Wikipedia, "Condition number", 

537 https://en.wikipedia.org/wiki/Condition_number 

538 

539 Examples 

540 -------- 

541 >>> from numpy.linalg import inv 

542 >>> a = np.array([[1., 2.], [3., 4.]]) 

543 >>> ainv = inv(a) 

544 >>> np.allclose(a @ ainv, np.eye(2)) 

545 True 

546 >>> np.allclose(ainv @ a, np.eye(2)) 

547 True 

548 

549 If a is a matrix object, then the return value is a matrix as well: 

550 

551 >>> ainv = inv(np.matrix(a)) 

552 >>> ainv 

553 matrix([[-2. , 1. ], 

554 [ 1.5, -0.5]]) 

555 

556 Inverses of several matrices can be computed at once: 

557 

558 >>> a = np.array([[[1., 2.], [3., 4.]], [[1, 3], [3, 5]]]) 

559 >>> inv(a) 

560 array([[[-2. , 1. ], 

561 [ 1.5 , -0.5 ]], 

562 [[-1.25, 0.75], 

563 [ 0.75, -0.25]]]) 

564 

565 If a matrix is close to singular, the computed inverse may not satisfy 

566 ``a @ ainv = ainv @ a = eye(a.shape[0])`` even if a `LinAlgError` 

567 is not raised: 

568 

569 >>> a = np.array([[2,4,6],[2,0,2],[6,8,14]]) 

570 >>> inv(a) # No errors raised 

571 array([[-1.12589991e+15, -5.62949953e+14, 5.62949953e+14], 

572 [-1.12589991e+15, -5.62949953e+14, 5.62949953e+14], 

573 [ 1.12589991e+15, 5.62949953e+14, -5.62949953e+14]]) 

574 >>> a @ inv(a) 

575 array([[ 0. , -0.5 , 0. ], # may vary 

576 [-0.5 , 0.625, 0.25 ], 

577 [ 0. , 0. , 1. ]]) 

578 

579 To detect ill-conditioned matrices, you can use `numpy.linalg.cond` to 

580 compute its *condition number* [1]_. The larger the condition number, the 

581 more ill-conditioned the matrix is. As a rule of thumb, if the condition 

582 number ``cond(a) = 10**k``, then you may lose up to ``k`` digits of 

583 accuracy on top of what would be lost to the numerical method due to loss 

584 of precision from arithmetic methods. 

585 

586 >>> from numpy.linalg import cond 

587 >>> cond(a) 

588 np.float64(8.659885634118668e+17) # may vary 

589 

590 It is also possible to detect ill-conditioning by inspecting the matrix's 

591 singular values directly. The ratio between the largest and the smallest 

592 singular value is the condition number: 

593 

594 >>> from numpy.linalg import svd 

595 >>> sigma = svd(a, compute_uv=False) # Do not compute singular vectors 

596 >>> sigma.max()/sigma.min() 

597 8.659885634118668e+17 # may vary 

598 

599 """ 

600 a, wrap = _makearray(a) 

601 _assert_stacked_2d(a) 

602 _assert_stacked_square(a) 

603 t, result_t = _commonType(a) 

604 

605 signature = 'D->D' if isComplexType(t) else 'd->d' 

606 with errstate(call=_raise_linalgerror_singular, invalid='call', 

607 over='ignore', divide='ignore', under='ignore'): 

608 ainv = _umath_linalg.inv(a, signature=signature) 

609 return wrap(ainv.astype(result_t, copy=False)) 

610 

611 

612def _matrix_power_dispatcher(a, n): 

613 return (a,) 

614 

615 

616@array_function_dispatch(_matrix_power_dispatcher) 

617def matrix_power(a, n): 

618 """ 

619 Raise a square matrix to the (integer) power `n`. 

620 

621 For positive integers `n`, the power is computed by repeated matrix 

622 squarings and matrix multiplications. If ``n == 0``, the identity matrix 

623 of the same shape as M is returned. If ``n < 0``, the inverse 

624 is computed and then raised to the ``abs(n)``. 

625 

626 .. note:: Stacks of object matrices are not currently supported. 

627 

628 Parameters 

629 ---------- 

630 a : (..., M, M) array_like 

631 Matrix to be "powered". 

632 n : int 

633 The exponent can be any integer or long integer, positive, 

634 negative, or zero. 

635 

636 Returns 

637 ------- 

638 a**n : (..., M, M) ndarray or matrix object 

639 The return value is the same shape and type as `M`; 

640 if the exponent is positive or zero then the type of the 

641 elements is the same as those of `M`. If the exponent is 

642 negative the elements are floating-point. 

643 

644 Raises 

645 ------ 

646 LinAlgError 

647 For matrices that are not square or that (for negative powers) cannot 

648 be inverted numerically. 

649 

650 Examples 

651 -------- 

652 >>> from numpy.linalg import matrix_power 

653 >>> i = np.array([[0, 1], [-1, 0]]) # matrix equiv. of the imaginary unit 

654 >>> matrix_power(i, 3) # should = -i 

655 array([[ 0, -1], 

656 [ 1, 0]]) 

657 >>> matrix_power(i, 0) 

658 array([[1, 0], 

659 [0, 1]]) 

660 >>> matrix_power(i, -3) # should = 1/(-i) = i, but w/ f.p. elements 

661 array([[ 0., 1.], 

662 [-1., 0.]]) 

663 

664 Somewhat more sophisticated example 

665 

666 >>> q = np.zeros((4, 4)) 

667 >>> q[0:2, 0:2] = -i 

668 >>> q[2:4, 2:4] = i 

669 >>> q # one of the three quaternion units not equal to 1 

670 array([[ 0., -1., 0., 0.], 

671 [ 1., 0., 0., 0.], 

672 [ 0., 0., 0., 1.], 

673 [ 0., 0., -1., 0.]]) 

674 >>> matrix_power(q, 2) # = -np.eye(4) 

675 array([[-1., 0., 0., 0.], 

676 [ 0., -1., 0., 0.], 

677 [ 0., 0., -1., 0.], 

678 [ 0., 0., 0., -1.]]) 

679 

680 """ 

681 a = asanyarray(a) 

682 _assert_stacked_2d(a) 

683 _assert_stacked_square(a) 

684 

685 try: 

686 n = operator.index(n) 

687 except TypeError as e: 

688 raise TypeError("exponent must be an integer") from e 

689 

690 # Fall back on dot for object arrays. Object arrays are not supported by 

691 # the current implementation of matmul using einsum 

692 if a.dtype != object: 

693 fmatmul = matmul 

694 elif a.ndim == 2: 

695 fmatmul = dot 

696 else: 

697 raise NotImplementedError( 

698 "matrix_power not supported for stacks of object arrays") 

699 

700 if n == 0: 

701 a = empty_like(a) 

702 a[...] = eye(a.shape[-2], dtype=a.dtype) 

703 return a 

704 

705 elif n < 0: 

706 a = inv(a) 

707 n = abs(n) 

708 

709 # short-cuts. 

710 if n == 1: 

711 return a 

712 

713 elif n == 2: 

714 return fmatmul(a, a) 

715 

716 elif n == 3: 

717 return fmatmul(fmatmul(a, a), a) 

718 

719 # Use binary decomposition to reduce the number of matrix multiplications. 

720 # Here, we iterate over the bits of n, from LSB to MSB, raise `a` to 

721 # increasing powers of 2, and multiply into the result as needed. 

722 z = result = None 

723 while n > 0: 

724 z = a if z is None else fmatmul(z, z) 

725 n, bit = divmod(n, 2) 

726 if bit: 

727 result = z if result is None else fmatmul(result, z) 

728 

729 return result 

730 

731 

732# Cholesky decomposition 

733 

734def _cholesky_dispatcher(a, /, *, upper=None): 

735 return (a,) 

736 

737 

738@array_function_dispatch(_cholesky_dispatcher) 

739def cholesky(a, /, *, upper=False): 

740 """ 

741 Cholesky decomposition. 

742 

743 Return the lower or upper Cholesky decomposition, ``L * L.H`` or 

744 ``U.H * U``, of the square matrix ``a``, where ``L`` is lower-triangular, 

745 ``U`` is upper-triangular, and ``.H`` is the conjugate transpose operator 

746 (which is the ordinary transpose if ``a`` is real-valued). ``a`` must be 

747 Hermitian (symmetric if real-valued) and positive-definite. No checking is 

748 performed to verify whether ``a`` is Hermitian or not. In addition, only 

749 the lower or upper-triangular and diagonal elements of ``a`` are used. 

750 Only ``L`` or ``U`` is actually returned. 

751 

752 Parameters 

753 ---------- 

754 a : (..., M, M) array_like 

755 Hermitian (symmetric if all elements are real), positive-definite 

756 input matrix. 

757 upper : bool 

758 If ``True``, the result must be the upper-triangular Cholesky factor. 

759 If ``False``, the result must be the lower-triangular Cholesky factor. 

760 Default: ``False``. 

761 

762 Returns 

763 ------- 

764 L : (..., M, M) array_like 

765 Lower or upper-triangular Cholesky factor of `a`. Returns a matrix 

766 object if `a` is a matrix object. 

767 

768 Raises 

769 ------ 

770 LinAlgError 

771 If the decomposition fails, for example, if `a` is not 

772 positive-definite. 

773 

774 See Also 

775 -------- 

776 scipy.linalg.cholesky : Similar function in SciPy. 

777 scipy.linalg.cholesky_banded : Cholesky decompose a banded Hermitian 

778 positive-definite matrix. 

779 scipy.linalg.cho_factor : Cholesky decomposition of a matrix, to use in 

780 `scipy.linalg.cho_solve`. 

781 

782 Notes 

783 ----- 

784 

785 .. versionadded:: 1.8.0 

786 

787 Broadcasting rules apply, see the `numpy.linalg` documentation for 

788 details. 

789 

790 The Cholesky decomposition is often used as a fast way of solving 

791 

792 .. math:: A \\mathbf{x} = \\mathbf{b} 

793 

794 (when `A` is both Hermitian/symmetric and positive-definite). 

795 

796 First, we solve for :math:`\\mathbf{y}` in 

797 

798 .. math:: L \\mathbf{y} = \\mathbf{b}, 

799 

800 and then for :math:`\\mathbf{x}` in 

801 

802 .. math:: L^{H} \\mathbf{x} = \\mathbf{y}. 

803 

804 Examples 

805 -------- 

806 >>> A = np.array([[1,-2j],[2j,5]]) 

807 >>> A 

808 array([[ 1.+0.j, -0.-2.j], 

809 [ 0.+2.j, 5.+0.j]]) 

810 >>> L = np.linalg.cholesky(A) 

811 >>> L 

812 array([[1.+0.j, 0.+0.j], 

813 [0.+2.j, 1.+0.j]]) 

814 >>> np.dot(L, L.T.conj()) # verify that L * L.H = A 

815 array([[1.+0.j, 0.-2.j], 

816 [0.+2.j, 5.+0.j]]) 

817 >>> A = [[1,-2j],[2j,5]] # what happens if A is only array_like? 

818 >>> np.linalg.cholesky(A) # an ndarray object is returned 

819 array([[1.+0.j, 0.+0.j], 

820 [0.+2.j, 1.+0.j]]) 

821 >>> # But a matrix object is returned if A is a matrix object 

822 >>> np.linalg.cholesky(np.matrix(A)) 

823 matrix([[ 1.+0.j, 0.+0.j], 

824 [ 0.+2.j, 1.+0.j]]) 

825 >>> # The upper-triangular Cholesky factor can also be obtained. 

826 >>> np.linalg.cholesky(A, upper=True) 

827 array([[1.-0.j, 0.-2.j], 

828 [0.-0.j, 1.-0.j]]) 

829 

830 """ 

831 gufunc = _umath_linalg.cholesky_up if upper else _umath_linalg.cholesky_lo 

832 a, wrap = _makearray(a) 

833 _assert_stacked_2d(a) 

834 _assert_stacked_square(a) 

835 t, result_t = _commonType(a) 

836 signature = 'D->D' if isComplexType(t) else 'd->d' 

837 with errstate(call=_raise_linalgerror_nonposdef, invalid='call', 

838 over='ignore', divide='ignore', under='ignore'): 

839 r = gufunc(a, signature=signature) 

840 return wrap(r.astype(result_t, copy=False)) 

841 

842 

843# outer product 

844 

845 

846def _outer_dispatcher(x1, x2): 

847 return (x1, x2) 

848 

849 

850@array_function_dispatch(_outer_dispatcher) 

851def outer(x1, x2, /): 

852 """ 

853 Compute the outer product of two vectors. 

854 

855 This function is Array API compatible. Compared to ``np.outer`` 

856 it accepts 1-dimensional inputs only. 

857 

858 Parameters 

859 ---------- 

860 x1 : (M,) array_like 

861 One-dimensional input array of size ``N``. 

862 Must have a numeric data type. 

863 x2 : (N,) array_like 

864 One-dimensional input array of size ``M``. 

865 Must have a numeric data type. 

866 

867 Returns 

868 ------- 

869 out : (M, N) ndarray 

870 ``out[i, j] = a[i] * b[j]`` 

871 

872 See also 

873 -------- 

874 outer 

875 

876 """ 

877 x1 = asanyarray(x1) 

878 x2 = asanyarray(x2) 

879 if x1.ndim != 1 or x2.ndim != 1: 

880 raise ValueError( 

881 "Input arrays must be one-dimensional, but they are " 

882 f"{x1.ndim=} and {x2.ndim=}." 

883 ) 

884 return _core_outer(x1, x2, out=None) 

885 

886 

887# QR decomposition 

888 

889 

890def _qr_dispatcher(a, mode=None): 

891 return (a,) 

892 

893 

894@array_function_dispatch(_qr_dispatcher) 

895def qr(a, mode='reduced'): 

896 """ 

897 Compute the qr factorization of a matrix. 

898 

899 Factor the matrix `a` as *qr*, where `q` is orthonormal and `r` is 

900 upper-triangular. 

901 

902 Parameters 

903 ---------- 

904 a : array_like, shape (..., M, N) 

905 An array-like object with the dimensionality of at least 2. 

906 mode : {'reduced', 'complete', 'r', 'raw'}, optional, default: 'reduced' 

907 If K = min(M, N), then 

908 

909 * 'reduced' : returns Q, R with dimensions (..., M, K), (..., K, N) 

910 * 'complete' : returns Q, R with dimensions (..., M, M), (..., M, N) 

911 * 'r' : returns R only with dimensions (..., K, N) 

912 * 'raw' : returns h, tau with dimensions (..., N, M), (..., K,) 

913 

914 The options 'reduced', 'complete, and 'raw' are new in numpy 1.8, 

915 see the notes for more information. The default is 'reduced', and to 

916 maintain backward compatibility with earlier versions of numpy both 

917 it and the old default 'full' can be omitted. Note that array h 

918 returned in 'raw' mode is transposed for calling Fortran. The 

919 'economic' mode is deprecated. The modes 'full' and 'economic' may 

920 be passed using only the first letter for backwards compatibility, 

921 but all others must be spelled out. See the Notes for more 

922 explanation. 

923 

924 

925 Returns 

926 ------- 

927 When mode is 'reduced' or 'complete', the result will be a namedtuple with 

928 the attributes `Q` and `R`. 

929 

930 Q : ndarray of float or complex, optional 

931 A matrix with orthonormal columns. When mode = 'complete' the 

932 result is an orthogonal/unitary matrix depending on whether or not 

933 a is real/complex. The determinant may be either +/- 1 in that 

934 case. In case the number of dimensions in the input array is 

935 greater than 2 then a stack of the matrices with above properties 

936 is returned. 

937 R : ndarray of float or complex, optional 

938 The upper-triangular matrix or a stack of upper-triangular 

939 matrices if the number of dimensions in the input array is greater 

940 than 2. 

941 (h, tau) : ndarrays of np.double or np.cdouble, optional 

942 The array h contains the Householder reflectors that generate q 

943 along with r. The tau array contains scaling factors for the 

944 reflectors. In the deprecated 'economic' mode only h is returned. 

945 

946 Raises 

947 ------ 

948 LinAlgError 

949 If factoring fails. 

950 

951 See Also 

952 -------- 

953 scipy.linalg.qr : Similar function in SciPy. 

954 scipy.linalg.rq : Compute RQ decomposition of a matrix. 

955 

956 Notes 

957 ----- 

958 This is an interface to the LAPACK routines ``dgeqrf``, ``zgeqrf``, 

959 ``dorgqr``, and ``zungqr``. 

960 

961 For more information on the qr factorization, see for example: 

962 https://en.wikipedia.org/wiki/QR_factorization 

963 

964 Subclasses of `ndarray` are preserved except for the 'raw' mode. So if 

965 `a` is of type `matrix`, all the return values will be matrices too. 

966 

967 New 'reduced', 'complete', and 'raw' options for mode were added in 

968 NumPy 1.8.0 and the old option 'full' was made an alias of 'reduced'. In 

969 addition the options 'full' and 'economic' were deprecated. Because 

970 'full' was the previous default and 'reduced' is the new default, 

971 backward compatibility can be maintained by letting `mode` default. 

972 The 'raw' option was added so that LAPACK routines that can multiply 

973 arrays by q using the Householder reflectors can be used. Note that in 

974 this case the returned arrays are of type np.double or np.cdouble and 

975 the h array is transposed to be FORTRAN compatible. No routines using 

976 the 'raw' return are currently exposed by numpy, but some are available 

977 in lapack_lite and just await the necessary work. 

978 

979 Examples 

980 -------- 

981 >>> a = np.random.randn(9, 6) 

982 >>> Q, R = np.linalg.qr(a) 

983 >>> np.allclose(a, np.dot(Q, R)) # a does equal QR 

984 True 

985 >>> R2 = np.linalg.qr(a, mode='r') 

986 >>> np.allclose(R, R2) # mode='r' returns the same R as mode='full' 

987 True 

988 >>> a = np.random.normal(size=(3, 2, 2)) # Stack of 2 x 2 matrices as input 

989 >>> Q, R = np.linalg.qr(a) 

990 >>> Q.shape 

991 (3, 2, 2) 

992 >>> R.shape 

993 (3, 2, 2) 

994 >>> np.allclose(a, np.matmul(Q, R)) 

995 True 

996 

997 Example illustrating a common use of `qr`: solving of least squares 

998 problems 

999 

1000 What are the least-squares-best `m` and `y0` in ``y = y0 + mx`` for 

1001 the following data: {(0,1), (1,0), (1,2), (2,1)}. (Graph the points 

1002 and you'll see that it should be y0 = 0, m = 1.) The answer is provided 

1003 by solving the over-determined matrix equation ``Ax = b``, where:: 

1004 

1005 A = array([[0, 1], [1, 1], [1, 1], [2, 1]]) 

1006 x = array([[y0], [m]]) 

1007 b = array([[1], [0], [2], [1]]) 

1008 

1009 If A = QR such that Q is orthonormal (which is always possible via 

1010 Gram-Schmidt), then ``x = inv(R) * (Q.T) * b``. (In numpy practice, 

1011 however, we simply use `lstsq`.) 

1012 

1013 >>> A = np.array([[0, 1], [1, 1], [1, 1], [2, 1]]) 

1014 >>> A 

1015 array([[0, 1], 

1016 [1, 1], 

1017 [1, 1], 

1018 [2, 1]]) 

1019 >>> b = np.array([1, 2, 2, 3]) 

1020 >>> Q, R = np.linalg.qr(A) 

1021 >>> p = np.dot(Q.T, b) 

1022 >>> np.dot(np.linalg.inv(R), p) 

1023 array([ 1., 1.]) 

1024 

1025 """ 

1026 if mode not in ('reduced', 'complete', 'r', 'raw'): 

1027 if mode in ('f', 'full'): 

1028 # 2013-04-01, 1.8 

1029 msg = "".join(( 

1030 "The 'full' option is deprecated in favor of 'reduced'.\n", 

1031 "For backward compatibility let mode default.")) 

1032 warnings.warn(msg, DeprecationWarning, stacklevel=2) 

1033 mode = 'reduced' 

1034 elif mode in ('e', 'economic'): 

1035 # 2013-04-01, 1.8 

1036 msg = "The 'economic' option is deprecated." 

1037 warnings.warn(msg, DeprecationWarning, stacklevel=2) 

1038 mode = 'economic' 

1039 else: 

1040 raise ValueError(f"Unrecognized mode '{mode}'") 

1041 

1042 a, wrap = _makearray(a) 

1043 _assert_stacked_2d(a) 

1044 m, n = a.shape[-2:] 

1045 t, result_t = _commonType(a) 

1046 a = a.astype(t, copy=True) 

1047 a = _to_native_byte_order(a) 

1048 mn = min(m, n) 

1049 

1050 if m <= n: 

1051 gufunc = _umath_linalg.qr_r_raw_m 

1052 else: 

1053 gufunc = _umath_linalg.qr_r_raw_n 

1054 

1055 signature = 'D->D' if isComplexType(t) else 'd->d' 

1056 with errstate(call=_raise_linalgerror_qr, invalid='call', 

1057 over='ignore', divide='ignore', under='ignore'): 

1058 tau = gufunc(a, signature=signature) 

1059 

1060 # handle modes that don't return q 

1061 if mode == 'r': 

1062 r = triu(a[..., :mn, :]) 

1063 r = r.astype(result_t, copy=False) 

1064 return wrap(r) 

1065 

1066 if mode == 'raw': 

1067 q = transpose(a) 

1068 q = q.astype(result_t, copy=False) 

1069 tau = tau.astype(result_t, copy=False) 

1070 return wrap(q), tau 

1071 

1072 if mode == 'economic': 

1073 a = a.astype(result_t, copy=False) 

1074 return wrap(a) 

1075 

1076 # mc is the number of columns in the resulting q 

1077 # matrix. If the mode is complete then it is 

1078 # same as number of rows, and if the mode is reduced, 

1079 # then it is the minimum of number of rows and columns. 

1080 if mode == 'complete' and m > n: 

1081 mc = m 

1082 gufunc = _umath_linalg.qr_complete 

1083 else: 

1084 mc = mn 

1085 gufunc = _umath_linalg.qr_reduced 

1086 

1087 signature = 'DD->D' if isComplexType(t) else 'dd->d' 

1088 with errstate(call=_raise_linalgerror_qr, invalid='call', 

1089 over='ignore', divide='ignore', under='ignore'): 

1090 q = gufunc(a, tau, signature=signature) 

1091 r = triu(a[..., :mc, :]) 

1092 

1093 q = q.astype(result_t, copy=False) 

1094 r = r.astype(result_t, copy=False) 

1095 

1096 return QRResult(wrap(q), wrap(r)) 

1097 

1098# Eigenvalues 

1099 

1100 

1101@array_function_dispatch(_unary_dispatcher) 

1102def eigvals(a): 

1103 """ 

1104 Compute the eigenvalues of a general matrix. 

1105 

1106 Main difference between `eigvals` and `eig`: the eigenvectors aren't 

1107 returned. 

1108 

1109 Parameters 

1110 ---------- 

1111 a : (..., M, M) array_like 

1112 A complex- or real-valued matrix whose eigenvalues will be computed. 

1113 

1114 Returns 

1115 ------- 

1116 w : (..., M,) ndarray 

1117 The eigenvalues, each repeated according to its multiplicity. 

1118 They are not necessarily ordered, nor are they necessarily 

1119 real for real matrices. 

1120 

1121 Raises 

1122 ------ 

1123 LinAlgError 

1124 If the eigenvalue computation does not converge. 

1125 

1126 See Also 

1127 -------- 

1128 eig : eigenvalues and right eigenvectors of general arrays 

1129 eigvalsh : eigenvalues of real symmetric or complex Hermitian 

1130 (conjugate symmetric) arrays. 

1131 eigh : eigenvalues and eigenvectors of real symmetric or complex 

1132 Hermitian (conjugate symmetric) arrays. 

1133 scipy.linalg.eigvals : Similar function in SciPy. 

1134 

1135 Notes 

1136 ----- 

1137 

1138 .. versionadded:: 1.8.0 

1139 

1140 Broadcasting rules apply, see the `numpy.linalg` documentation for 

1141 details. 

1142 

1143 This is implemented using the ``_geev`` LAPACK routines which compute 

1144 the eigenvalues and eigenvectors of general square arrays. 

1145 

1146 Examples 

1147 -------- 

1148 Illustration, using the fact that the eigenvalues of a diagonal matrix 

1149 are its diagonal elements, that multiplying a matrix on the left 

1150 by an orthogonal matrix, `Q`, and on the right by `Q.T` (the transpose 

1151 of `Q`), preserves the eigenvalues of the "middle" matrix. In other words, 

1152 if `Q` is orthogonal, then ``Q * A * Q.T`` has the same eigenvalues as 

1153 ``A``: 

1154 

1155 >>> from numpy import linalg as LA 

1156 >>> x = np.random.random() 

1157 >>> Q = np.array([[np.cos(x), -np.sin(x)], [np.sin(x), np.cos(x)]]) 

1158 >>> LA.norm(Q[0, :]), LA.norm(Q[1, :]), np.dot(Q[0, :],Q[1, :]) 

1159 (1.0, 1.0, 0.0) 

1160 

1161 Now multiply a diagonal matrix by ``Q`` on one side and 

1162 by ``Q.T`` on the other: 

1163 

1164 >>> D = np.diag((-1,1)) 

1165 >>> LA.eigvals(D) 

1166 array([-1., 1.]) 

1167 >>> A = np.dot(Q, D) 

1168 >>> A = np.dot(A, Q.T) 

1169 >>> LA.eigvals(A) 

1170 array([ 1., -1.]) # random 

1171 

1172 """ 

1173 a, wrap = _makearray(a) 

1174 _assert_stacked_2d(a) 

1175 _assert_stacked_square(a) 

1176 _assert_finite(a) 

1177 t, result_t = _commonType(a) 

1178 

1179 signature = 'D->D' if isComplexType(t) else 'd->D' 

1180 with errstate(call=_raise_linalgerror_eigenvalues_nonconvergence, 

1181 invalid='call', over='ignore', divide='ignore', 

1182 under='ignore'): 

1183 w = _umath_linalg.eigvals(a, signature=signature) 

1184 

1185 if not isComplexType(t): 

1186 if all(w.imag == 0): 

1187 w = w.real 

1188 result_t = _realType(result_t) 

1189 else: 

1190 result_t = _complexType(result_t) 

1191 

1192 return w.astype(result_t, copy=False) 

1193 

1194 

1195def _eigvalsh_dispatcher(a, UPLO=None): 

1196 return (a,) 

1197 

1198 

1199@array_function_dispatch(_eigvalsh_dispatcher) 

1200def eigvalsh(a, UPLO='L'): 

1201 """ 

1202 Compute the eigenvalues of a complex Hermitian or real symmetric matrix. 

1203 

1204 Main difference from eigh: the eigenvectors are not computed. 

1205 

1206 Parameters 

1207 ---------- 

1208 a : (..., M, M) array_like 

1209 A complex- or real-valued matrix whose eigenvalues are to be 

1210 computed. 

1211 UPLO : {'L', 'U'}, optional 

1212 Specifies whether the calculation is done with the lower triangular 

1213 part of `a` ('L', default) or the upper triangular part ('U'). 

1214 Irrespective of this value only the real parts of the diagonal will 

1215 be considered in the computation to preserve the notion of a Hermitian 

1216 matrix. It therefore follows that the imaginary part of the diagonal 

1217 will always be treated as zero. 

1218 

1219 Returns 

1220 ------- 

1221 w : (..., M,) ndarray 

1222 The eigenvalues in ascending order, each repeated according to 

1223 its multiplicity. 

1224 

1225 Raises 

1226 ------ 

1227 LinAlgError 

1228 If the eigenvalue computation does not converge. 

1229 

1230 See Also 

1231 -------- 

1232 eigh : eigenvalues and eigenvectors of real symmetric or complex Hermitian 

1233 (conjugate symmetric) arrays. 

1234 eigvals : eigenvalues of general real or complex arrays. 

1235 eig : eigenvalues and right eigenvectors of general real or complex 

1236 arrays. 

1237 scipy.linalg.eigvalsh : Similar function in SciPy. 

1238 

1239 Notes 

1240 ----- 

1241 

1242 .. versionadded:: 1.8.0 

1243 

1244 Broadcasting rules apply, see the `numpy.linalg` documentation for 

1245 details. 

1246 

1247 The eigenvalues are computed using LAPACK routines ``_syevd``, ``_heevd``. 

1248 

1249 Examples 

1250 -------- 

1251 >>> from numpy import linalg as LA 

1252 >>> a = np.array([[1, -2j], [2j, 5]]) 

1253 >>> LA.eigvalsh(a) 

1254 array([ 0.17157288, 5.82842712]) # may vary 

1255 

1256 >>> # demonstrate the treatment of the imaginary part of the diagonal 

1257 >>> a = np.array([[5+2j, 9-2j], [0+2j, 2-1j]]) 

1258 >>> a 

1259 array([[5.+2.j, 9.-2.j], 

1260 [0.+2.j, 2.-1.j]]) 

1261 >>> # with UPLO='L' this is numerically equivalent to using LA.eigvals() 

1262 >>> # with: 

1263 >>> b = np.array([[5.+0.j, 0.-2.j], [0.+2.j, 2.-0.j]]) 

1264 >>> b 

1265 array([[5.+0.j, 0.-2.j], 

1266 [0.+2.j, 2.+0.j]]) 

1267 >>> wa = LA.eigvalsh(a) 

1268 >>> wb = LA.eigvals(b) 

1269 >>> wa; wb 

1270 array([1., 6.]) 

1271 array([6.+0.j, 1.+0.j]) 

1272 

1273 """ 

1274 UPLO = UPLO.upper() 

1275 if UPLO not in ('L', 'U'): 

1276 raise ValueError("UPLO argument must be 'L' or 'U'") 

1277 

1278 if UPLO == 'L': 

1279 gufunc = _umath_linalg.eigvalsh_lo 

1280 else: 

1281 gufunc = _umath_linalg.eigvalsh_up 

1282 

1283 a, wrap = _makearray(a) 

1284 _assert_stacked_2d(a) 

1285 _assert_stacked_square(a) 

1286 t, result_t = _commonType(a) 

1287 signature = 'D->d' if isComplexType(t) else 'd->d' 

1288 with errstate(call=_raise_linalgerror_eigenvalues_nonconvergence, 

1289 invalid='call', over='ignore', divide='ignore', 

1290 under='ignore'): 

1291 w = gufunc(a, signature=signature) 

1292 return w.astype(_realType(result_t), copy=False) 

1293 

1294def _convertarray(a): 

1295 t, result_t = _commonType(a) 

1296 a = a.astype(t).T.copy() 

1297 return a, t, result_t 

1298 

1299 

1300# Eigenvectors 

1301 

1302 

1303@array_function_dispatch(_unary_dispatcher) 

1304def eig(a): 

1305 """ 

1306 Compute the eigenvalues and right eigenvectors of a square array. 

1307 

1308 Parameters 

1309 ---------- 

1310 a : (..., M, M) array 

1311 Matrices for which the eigenvalues and right eigenvectors will 

1312 be computed 

1313 

1314 Returns 

1315 ------- 

1316 A namedtuple with the following attributes: 

1317 

1318 eigenvalues : (..., M) array 

1319 The eigenvalues, each repeated according to its multiplicity. 

1320 The eigenvalues are not necessarily ordered. The resulting 

1321 array will be of complex type, unless the imaginary part is 

1322 zero in which case it will be cast to a real type. When `a` 

1323 is real the resulting eigenvalues will be real (0 imaginary 

1324 part) or occur in conjugate pairs 

1325 

1326 eigenvectors : (..., M, M) array 

1327 The normalized (unit "length") eigenvectors, such that the 

1328 column ``eigenvectors[:,i]`` is the eigenvector corresponding to the 

1329 eigenvalue ``eigenvalues[i]``. 

1330 

1331 Raises 

1332 ------ 

1333 LinAlgError 

1334 If the eigenvalue computation does not converge. 

1335 

1336 See Also 

1337 -------- 

1338 eigvals : eigenvalues of a non-symmetric array. 

1339 eigh : eigenvalues and eigenvectors of a real symmetric or complex 

1340 Hermitian (conjugate symmetric) array. 

1341 eigvalsh : eigenvalues of a real symmetric or complex Hermitian 

1342 (conjugate symmetric) array. 

1343 scipy.linalg.eig : Similar function in SciPy that also solves the 

1344 generalized eigenvalue problem. 

1345 scipy.linalg.schur : Best choice for unitary and other non-Hermitian 

1346 normal matrices. 

1347 

1348 Notes 

1349 ----- 

1350 

1351 .. versionadded:: 1.8.0 

1352 

1353 Broadcasting rules apply, see the `numpy.linalg` documentation for 

1354 details. 

1355 

1356 This is implemented using the ``_geev`` LAPACK routines which compute 

1357 the eigenvalues and eigenvectors of general square arrays. 

1358 

1359 The number `w` is an eigenvalue of `a` if there exists a vector `v` such 

1360 that ``a @ v = w * v``. Thus, the arrays `a`, `eigenvalues`, and 

1361 `eigenvectors` satisfy the equations ``a @ eigenvectors[:,i] = 

1362 eigenvalues[i] * eigenvectors[:,i]`` for :math:`i \\in \\{0,...,M-1\\}`. 

1363 

1364 The array `eigenvectors` may not be of maximum rank, that is, some of the 

1365 columns may be linearly dependent, although round-off error may obscure 

1366 that fact. If the eigenvalues are all different, then theoretically the 

1367 eigenvectors are linearly independent and `a` can be diagonalized by a 

1368 similarity transformation using `eigenvectors`, i.e, ``inv(eigenvectors) @ 

1369 a @ eigenvectors`` is diagonal. 

1370 

1371 For non-Hermitian normal matrices the SciPy function `scipy.linalg.schur` 

1372 is preferred because the matrix `eigenvectors` is guaranteed to be 

1373 unitary, which is not the case when using `eig`. The Schur factorization 

1374 produces an upper triangular matrix rather than a diagonal matrix, but for 

1375 normal matrices only the diagonal of the upper triangular matrix is 

1376 needed, the rest is roundoff error. 

1377 

1378 Finally, it is emphasized that `eigenvectors` consists of the *right* (as 

1379 in right-hand side) eigenvectors of `a`. A vector `y` satisfying ``y.T @ a 

1380 = z * y.T`` for some number `z` is called a *left* eigenvector of `a`, 

1381 and, in general, the left and right eigenvectors of a matrix are not 

1382 necessarily the (perhaps conjugate) transposes of each other. 

1383 

1384 References 

1385 ---------- 

1386 G. Strang, *Linear Algebra and Its Applications*, 2nd Ed., Orlando, FL, 

1387 Academic Press, Inc., 1980, Various pp. 

1388 

1389 Examples 

1390 -------- 

1391 >>> from numpy import linalg as LA 

1392 

1393 (Almost) trivial example with real eigenvalues and eigenvectors. 

1394 

1395 >>> eigenvalues, eigenvectors = LA.eig(np.diag((1, 2, 3))) 

1396 >>> eigenvalues 

1397 array([1., 2., 3.]) 

1398 >>> eigenvectors 

1399 array([[1., 0., 0.], 

1400 [0., 1., 0.], 

1401 [0., 0., 1.]]) 

1402 

1403 Real matrix possessing complex eigenvalues and eigenvectors; 

1404 note that the eigenvalues are complex conjugates of each other. 

1405 

1406 >>> eigenvalues, eigenvectors = LA.eig(np.array([[1, -1], [1, 1]])) 

1407 >>> eigenvalues 

1408 array([1.+1.j, 1.-1.j]) 

1409 >>> eigenvectors 

1410 array([[0.70710678+0.j , 0.70710678-0.j ], 

1411 [0. -0.70710678j, 0. +0.70710678j]]) 

1412 

1413 Complex-valued matrix with real eigenvalues (but complex-valued 

1414 eigenvectors); note that ``a.conj().T == a``, i.e., `a` is Hermitian. 

1415 

1416 >>> a = np.array([[1, 1j], [-1j, 1]]) 

1417 >>> eigenvalues, eigenvectors = LA.eig(a) 

1418 >>> eigenvalues 

1419 array([2.+0.j, 0.+0.j]) 

1420 >>> eigenvectors 

1421 array([[ 0. +0.70710678j, 0.70710678+0.j ], # may vary 

1422 [ 0.70710678+0.j , -0. +0.70710678j]]) 

1423 

1424 Be careful about round-off error! 

1425 

1426 >>> a = np.array([[1 + 1e-9, 0], [0, 1 - 1e-9]]) 

1427 >>> # Theor. eigenvalues are 1 +/- 1e-9 

1428 >>> eigenvalues, eigenvectors = LA.eig(a) 

1429 >>> eigenvalues 

1430 array([1., 1.]) 

1431 >>> eigenvectors 

1432 array([[1., 0.], 

1433 [0., 1.]]) 

1434 

1435 """ 

1436 a, wrap = _makearray(a) 

1437 _assert_stacked_2d(a) 

1438 _assert_stacked_square(a) 

1439 _assert_finite(a) 

1440 t, result_t = _commonType(a) 

1441 

1442 signature = 'D->DD' if isComplexType(t) else 'd->DD' 

1443 with errstate(call=_raise_linalgerror_eigenvalues_nonconvergence, 

1444 invalid='call', over='ignore', divide='ignore', 

1445 under='ignore'): 

1446 w, vt = _umath_linalg.eig(a, signature=signature) 

1447 

1448 if not isComplexType(t) and all(w.imag == 0.0): 

1449 w = w.real 

1450 vt = vt.real 

1451 result_t = _realType(result_t) 

1452 else: 

1453 result_t = _complexType(result_t) 

1454 

1455 vt = vt.astype(result_t, copy=False) 

1456 return EigResult(w.astype(result_t, copy=False), wrap(vt)) 

1457 

1458 

1459@array_function_dispatch(_eigvalsh_dispatcher) 

1460def eigh(a, UPLO='L'): 

1461 """ 

1462 Return the eigenvalues and eigenvectors of a complex Hermitian 

1463 (conjugate symmetric) or a real symmetric matrix. 

1464 

1465 Returns two objects, a 1-D array containing the eigenvalues of `a`, and 

1466 a 2-D square array or matrix (depending on the input type) of the 

1467 corresponding eigenvectors (in columns). 

1468 

1469 Parameters 

1470 ---------- 

1471 a : (..., M, M) array 

1472 Hermitian or real symmetric matrices whose eigenvalues and 

1473 eigenvectors are to be computed. 

1474 UPLO : {'L', 'U'}, optional 

1475 Specifies whether the calculation is done with the lower triangular 

1476 part of `a` ('L', default) or the upper triangular part ('U'). 

1477 Irrespective of this value only the real parts of the diagonal will 

1478 be considered in the computation to preserve the notion of a Hermitian 

1479 matrix. It therefore follows that the imaginary part of the diagonal 

1480 will always be treated as zero. 

1481 

1482 Returns 

1483 ------- 

1484 A namedtuple with the following attributes: 

1485 

1486 eigenvalues : (..., M) ndarray 

1487 The eigenvalues in ascending order, each repeated according to 

1488 its multiplicity. 

1489 eigenvectors : {(..., M, M) ndarray, (..., M, M) matrix} 

1490 The column ``eigenvectors[:, i]`` is the normalized eigenvector 

1491 corresponding to the eigenvalue ``eigenvalues[i]``. Will return a 

1492 matrix object if `a` is a matrix object. 

1493 

1494 Raises 

1495 ------ 

1496 LinAlgError 

1497 If the eigenvalue computation does not converge. 

1498 

1499 See Also 

1500 -------- 

1501 eigvalsh : eigenvalues of real symmetric or complex Hermitian 

1502 (conjugate symmetric) arrays. 

1503 eig : eigenvalues and right eigenvectors for non-symmetric arrays. 

1504 eigvals : eigenvalues of non-symmetric arrays. 

1505 scipy.linalg.eigh : Similar function in SciPy (but also solves the 

1506 generalized eigenvalue problem). 

1507 

1508 Notes 

1509 ----- 

1510 

1511 .. versionadded:: 1.8.0 

1512 

1513 Broadcasting rules apply, see the `numpy.linalg` documentation for 

1514 details. 

1515 

1516 The eigenvalues/eigenvectors are computed using LAPACK routines ``_syevd``, 

1517 ``_heevd``. 

1518 

1519 The eigenvalues of real symmetric or complex Hermitian matrices are always 

1520 real. [1]_ The array `eigenvalues` of (column) eigenvectors is unitary and 

1521 `a`, `eigenvalues`, and `eigenvectors` satisfy the equations ``dot(a, 

1522 eigenvectors[:, i]) = eigenvalues[i] * eigenvectors[:, i]``. 

1523 

1524 References 

1525 ---------- 

1526 .. [1] G. Strang, *Linear Algebra and Its Applications*, 2nd Ed., Orlando, 

1527 FL, Academic Press, Inc., 1980, pg. 222. 

1528 

1529 Examples 

1530 -------- 

1531 >>> from numpy import linalg as LA 

1532 >>> a = np.array([[1, -2j], [2j, 5]]) 

1533 >>> a 

1534 array([[ 1.+0.j, -0.-2.j], 

1535 [ 0.+2.j, 5.+0.j]]) 

1536 >>> eigenvalues, eigenvectors = LA.eigh(a) 

1537 >>> eigenvalues 

1538 array([0.17157288, 5.82842712]) 

1539 >>> eigenvectors 

1540 array([[-0.92387953+0.j , -0.38268343+0.j ], # may vary 

1541 [ 0. +0.38268343j, 0. -0.92387953j]]) 

1542 

1543 >>> (np.dot(a, eigenvectors[:, 0]) - 

1544 ... eigenvalues[0] * eigenvectors[:, 0]) # verify 1st eigenval/vec pair 

1545 array([5.55111512e-17+0.0000000e+00j, 0.00000000e+00+1.2490009e-16j]) 

1546 >>> (np.dot(a, eigenvectors[:, 1]) - 

1547 ... eigenvalues[1] * eigenvectors[:, 1]) # verify 2nd eigenval/vec pair 

1548 array([0.+0.j, 0.+0.j]) 

1549 

1550 >>> A = np.matrix(a) # what happens if input is a matrix object 

1551 >>> A 

1552 matrix([[ 1.+0.j, -0.-2.j], 

1553 [ 0.+2.j, 5.+0.j]]) 

1554 >>> eigenvalues, eigenvectors = LA.eigh(A) 

1555 >>> eigenvalues 

1556 array([0.17157288, 5.82842712]) 

1557 >>> eigenvectors 

1558 matrix([[-0.92387953+0.j , -0.38268343+0.j ], # may vary 

1559 [ 0. +0.38268343j, 0. -0.92387953j]]) 

1560 

1561 >>> # demonstrate the treatment of the imaginary part of the diagonal 

1562 >>> a = np.array([[5+2j, 9-2j], [0+2j, 2-1j]]) 

1563 >>> a 

1564 array([[5.+2.j, 9.-2.j], 

1565 [0.+2.j, 2.-1.j]]) 

1566 >>> # with UPLO='L' this is numerically equivalent to using LA.eig() with: 

1567 >>> b = np.array([[5.+0.j, 0.-2.j], [0.+2.j, 2.-0.j]]) 

1568 >>> b 

1569 array([[5.+0.j, 0.-2.j], 

1570 [0.+2.j, 2.+0.j]]) 

1571 >>> wa, va = LA.eigh(a) 

1572 >>> wb, vb = LA.eig(b) 

1573 >>> wa; wb 

1574 array([1., 6.]) 

1575 array([6.+0.j, 1.+0.j]) 

1576 >>> va; vb 

1577 array([[-0.4472136 +0.j , -0.89442719+0.j ], # may vary 

1578 [ 0. +0.89442719j, 0. -0.4472136j ]]) 

1579 array([[ 0.89442719+0.j , -0. +0.4472136j], 

1580 [-0. +0.4472136j, 0.89442719+0.j ]]) 

1581 

1582 """ 

1583 UPLO = UPLO.upper() 

1584 if UPLO not in ('L', 'U'): 

1585 raise ValueError("UPLO argument must be 'L' or 'U'") 

1586 

1587 a, wrap = _makearray(a) 

1588 _assert_stacked_2d(a) 

1589 _assert_stacked_square(a) 

1590 t, result_t = _commonType(a) 

1591 

1592 if UPLO == 'L': 

1593 gufunc = _umath_linalg.eigh_lo 

1594 else: 

1595 gufunc = _umath_linalg.eigh_up 

1596 

1597 signature = 'D->dD' if isComplexType(t) else 'd->dd' 

1598 with errstate(call=_raise_linalgerror_eigenvalues_nonconvergence, 

1599 invalid='call', over='ignore', divide='ignore', 

1600 under='ignore'): 

1601 w, vt = gufunc(a, signature=signature) 

1602 w = w.astype(_realType(result_t), copy=False) 

1603 vt = vt.astype(result_t, copy=False) 

1604 return EighResult(w, wrap(vt)) 

1605 

1606 

1607# Singular value decomposition 

1608 

1609def _svd_dispatcher(a, full_matrices=None, compute_uv=None, hermitian=None): 

1610 return (a,) 

1611 

1612 

1613@array_function_dispatch(_svd_dispatcher) 

1614def svd(a, full_matrices=True, compute_uv=True, hermitian=False): 

1615 """ 

1616 Singular Value Decomposition. 

1617 

1618 When `a` is a 2D array, and ``full_matrices=False``, then it is 

1619 factorized as ``u @ np.diag(s) @ vh = (u * s) @ vh``, where 

1620 `u` and the Hermitian transpose of `vh` are 2D arrays with 

1621 orthonormal columns and `s` is a 1D array of `a`'s singular 

1622 values. When `a` is higher-dimensional, SVD is applied in 

1623 stacked mode as explained below. 

1624 

1625 Parameters 

1626 ---------- 

1627 a : (..., M, N) array_like 

1628 A real or complex array with ``a.ndim >= 2``. 

1629 full_matrices : bool, optional 

1630 If True (default), `u` and `vh` have the shapes ``(..., M, M)`` and 

1631 ``(..., N, N)``, respectively. Otherwise, the shapes are 

1632 ``(..., M, K)`` and ``(..., K, N)``, respectively, where 

1633 ``K = min(M, N)``. 

1634 compute_uv : bool, optional 

1635 Whether or not to compute `u` and `vh` in addition to `s`. True 

1636 by default. 

1637 hermitian : bool, optional 

1638 If True, `a` is assumed to be Hermitian (symmetric if real-valued), 

1639 enabling a more efficient method for finding singular values. 

1640 Defaults to False. 

1641 

1642 .. versionadded:: 1.17.0 

1643 

1644 Returns 

1645 ------- 

1646 When `compute_uv` is True, the result is a namedtuple with the following 

1647 attribute names: 

1648 

1649 U : { (..., M, M), (..., M, K) } array 

1650 Unitary array(s). The first ``a.ndim - 2`` dimensions have the same 

1651 size as those of the input `a`. The size of the last two dimensions 

1652 depends on the value of `full_matrices`. Only returned when 

1653 `compute_uv` is True. 

1654 S : (..., K) array 

1655 Vector(s) with the singular values, within each vector sorted in 

1656 descending order. The first ``a.ndim - 2`` dimensions have the same 

1657 size as those of the input `a`. 

1658 Vh : { (..., N, N), (..., K, N) } array 

1659 Unitary array(s). The first ``a.ndim - 2`` dimensions have the same 

1660 size as those of the input `a`. The size of the last two dimensions 

1661 depends on the value of `full_matrices`. Only returned when 

1662 `compute_uv` is True. 

1663 

1664 Raises 

1665 ------ 

1666 LinAlgError 

1667 If SVD computation does not converge. 

1668 

1669 See Also 

1670 -------- 

1671 scipy.linalg.svd : Similar function in SciPy. 

1672 scipy.linalg.svdvals : Compute singular values of a matrix. 

1673 

1674 Notes 

1675 ----- 

1676 

1677 .. versionchanged:: 1.8.0 

1678 Broadcasting rules apply, see the `numpy.linalg` documentation for 

1679 details. 

1680 

1681 The decomposition is performed using LAPACK routine ``_gesdd``. 

1682 

1683 SVD is usually described for the factorization of a 2D matrix :math:`A`. 

1684 The higher-dimensional case will be discussed below. In the 2D case, SVD is 

1685 written as :math:`A = U S V^H`, where :math:`A = a`, :math:`U= u`, 

1686 :math:`S= \\mathtt{np.diag}(s)` and :math:`V^H = vh`. The 1D array `s` 

1687 contains the singular values of `a` and `u` and `vh` are unitary. The rows 

1688 of `vh` are the eigenvectors of :math:`A^H A` and the columns of `u` are 

1689 the eigenvectors of :math:`A A^H`. In both cases the corresponding 

1690 (possibly non-zero) eigenvalues are given by ``s**2``. 

1691 

1692 If `a` has more than two dimensions, then broadcasting rules apply, as 

1693 explained in :ref:`routines.linalg-broadcasting`. This means that SVD is 

1694 working in "stacked" mode: it iterates over all indices of the first 

1695 ``a.ndim - 2`` dimensions and for each combination SVD is applied to the 

1696 last two indices. The matrix `a` can be reconstructed from the 

1697 decomposition with either ``(u * s[..., None, :]) @ vh`` or 

1698 ``u @ (s[..., None] * vh)``. (The ``@`` operator can be replaced by the 

1699 function ``np.matmul`` for python versions below 3.5.) 

1700 

1701 If `a` is a ``matrix`` object (as opposed to an ``ndarray``), then so are 

1702 all the return values. 

1703 

1704 Examples 

1705 -------- 

1706 >>> a = np.random.randn(9, 6) + 1j*np.random.randn(9, 6) 

1707 >>> b = np.random.randn(2, 7, 8, 3) + 1j*np.random.randn(2, 7, 8, 3) 

1708 

1709 Reconstruction based on full SVD, 2D case: 

1710 

1711 >>> U, S, Vh = np.linalg.svd(a, full_matrices=True) 

1712 >>> U.shape, S.shape, Vh.shape 

1713 ((9, 9), (6,), (6, 6)) 

1714 >>> np.allclose(a, np.dot(U[:, :6] * S, Vh)) 

1715 True 

1716 >>> smat = np.zeros((9, 6), dtype=complex) 

1717 >>> smat[:6, :6] = np.diag(S) 

1718 >>> np.allclose(a, np.dot(U, np.dot(smat, Vh))) 

1719 True 

1720 

1721 Reconstruction based on reduced SVD, 2D case: 

1722 

1723 >>> U, S, Vh = np.linalg.svd(a, full_matrices=False) 

1724 >>> U.shape, S.shape, Vh.shape 

1725 ((9, 6), (6,), (6, 6)) 

1726 >>> np.allclose(a, np.dot(U * S, Vh)) 

1727 True 

1728 >>> smat = np.diag(S) 

1729 >>> np.allclose(a, np.dot(U, np.dot(smat, Vh))) 

1730 True 

1731 

1732 Reconstruction based on full SVD, 4D case: 

1733 

1734 >>> U, S, Vh = np.linalg.svd(b, full_matrices=True) 

1735 >>> U.shape, S.shape, Vh.shape 

1736 ((2, 7, 8, 8), (2, 7, 3), (2, 7, 3, 3)) 

1737 >>> np.allclose(b, np.matmul(U[..., :3] * S[..., None, :], Vh)) 

1738 True 

1739 >>> np.allclose(b, np.matmul(U[..., :3], S[..., None] * Vh)) 

1740 True 

1741 

1742 Reconstruction based on reduced SVD, 4D case: 

1743 

1744 >>> U, S, Vh = np.linalg.svd(b, full_matrices=False) 

1745 >>> U.shape, S.shape, Vh.shape 

1746 ((2, 7, 8, 3), (2, 7, 3), (2, 7, 3, 3)) 

1747 >>> np.allclose(b, np.matmul(U * S[..., None, :], Vh)) 

1748 True 

1749 >>> np.allclose(b, np.matmul(U, S[..., None] * Vh)) 

1750 True 

1751 

1752 """ 

1753 import numpy as _nx 

1754 a, wrap = _makearray(a) 

1755 

1756 if hermitian: 

1757 # note: lapack svd returns eigenvalues with s ** 2 sorted descending, 

1758 # but eig returns s sorted ascending, so we re-order the eigenvalues 

1759 # and related arrays to have the correct order 

1760 if compute_uv: 

1761 s, u = eigh(a) 

1762 sgn = sign(s) 

1763 s = abs(s) 

1764 sidx = argsort(s)[..., ::-1] 

1765 sgn = _nx.take_along_axis(sgn, sidx, axis=-1) 

1766 s = _nx.take_along_axis(s, sidx, axis=-1) 

1767 u = _nx.take_along_axis(u, sidx[..., None, :], axis=-1) 

1768 # singular values are unsigned, move the sign into v 

1769 vt = transpose(u * sgn[..., None, :]).conjugate() 

1770 return SVDResult(wrap(u), s, wrap(vt)) 

1771 else: 

1772 s = eigvalsh(a) 

1773 s = abs(s) 

1774 return sort(s)[..., ::-1] 

1775 

1776 _assert_stacked_2d(a) 

1777 t, result_t = _commonType(a) 

1778 

1779 m, n = a.shape[-2:] 

1780 if compute_uv: 

1781 if full_matrices: 

1782 if m < n: 

1783 gufunc = _umath_linalg.svd_m_f 

1784 else: 

1785 gufunc = _umath_linalg.svd_n_f 

1786 else: 

1787 if m < n: 

1788 gufunc = _umath_linalg.svd_m_s 

1789 else: 

1790 gufunc = _umath_linalg.svd_n_s 

1791 

1792 signature = 'D->DdD' if isComplexType(t) else 'd->ddd' 

1793 with errstate(call=_raise_linalgerror_svd_nonconvergence, 

1794 invalid='call', over='ignore', divide='ignore', 

1795 under='ignore'): 

1796 u, s, vh = gufunc(a, signature=signature) 

1797 u = u.astype(result_t, copy=False) 

1798 s = s.astype(_realType(result_t), copy=False) 

1799 vh = vh.astype(result_t, copy=False) 

1800 return SVDResult(wrap(u), s, wrap(vh)) 

1801 else: 

1802 if m < n: 

1803 gufunc = _umath_linalg.svd_m 

1804 else: 

1805 gufunc = _umath_linalg.svd_n 

1806 

1807 signature = 'D->d' if isComplexType(t) else 'd->d' 

1808 with errstate(call=_raise_linalgerror_svd_nonconvergence, 

1809 invalid='call', over='ignore', divide='ignore', 

1810 under='ignore'): 

1811 s = gufunc(a, signature=signature) 

1812 s = s.astype(_realType(result_t), copy=False) 

1813 return s 

1814 

1815 

1816def _svdvals_dispatcher(x): 

1817 return (x,) 

1818 

1819 

1820@array_function_dispatch(_svdvals_dispatcher) 

1821def svdvals(x, /): 

1822 """ 

1823 Returns the singular values of a matrix (or a stack of matrices) ``x``. 

1824 When x is a stack of matrices, the function will compute the singular 

1825 values for each matrix in the stack. 

1826 

1827 This function is Array API compatible. 

1828 

1829 Calling ``np.svdvals(x)`` to get singular values is the same as 

1830 ``np.svd(x, compute_uv=False, hermitian=False)``. 

1831 

1832 Parameters 

1833 ---------- 

1834 x : (..., M, N) array_like 

1835 Input array having shape (..., M, N) and whose last two 

1836 dimensions form matrices on which to perform singular value 

1837 decomposition. Should have a floating-point data type. 

1838 

1839 Returns 

1840 ------- 

1841 out : ndarray 

1842 An array with shape (..., K) that contains the vector(s) 

1843 of singular values of length K, where K = min(M, N). 

1844 

1845 See Also 

1846 -------- 

1847 scipy.linalg.svdvals : Compute singular values of a matrix. 

1848 

1849 """ 

1850 return svd(x, compute_uv=False, hermitian=False) 

1851 

1852 

1853def _cond_dispatcher(x, p=None): 

1854 return (x,) 

1855 

1856 

1857@array_function_dispatch(_cond_dispatcher) 

1858def cond(x, p=None): 

1859 """ 

1860 Compute the condition number of a matrix. 

1861 

1862 This function is capable of returning the condition number using 

1863 one of seven different norms, depending on the value of `p` (see 

1864 Parameters below). 

1865 

1866 Parameters 

1867 ---------- 

1868 x : (..., M, N) array_like 

1869 The matrix whose condition number is sought. 

1870 p : {None, 1, -1, 2, -2, inf, -inf, 'fro'}, optional 

1871 Order of the norm used in the condition number computation: 

1872 

1873 ===== ============================ 

1874 p norm for matrices 

1875 ===== ============================ 

1876 None 2-norm, computed directly using the ``SVD`` 

1877 'fro' Frobenius norm 

1878 inf max(sum(abs(x), axis=1)) 

1879 -inf min(sum(abs(x), axis=1)) 

1880 1 max(sum(abs(x), axis=0)) 

1881 -1 min(sum(abs(x), axis=0)) 

1882 2 2-norm (largest sing. value) 

1883 -2 smallest singular value 

1884 ===== ============================ 

1885 

1886 inf means the `numpy.inf` object, and the Frobenius norm is 

1887 the root-of-sum-of-squares norm. 

1888 

1889 Returns 

1890 ------- 

1891 c : {float, inf} 

1892 The condition number of the matrix. May be infinite. 

1893 

1894 See Also 

1895 -------- 

1896 numpy.linalg.norm 

1897 

1898 Notes 

1899 ----- 

1900 The condition number of `x` is defined as the norm of `x` times the 

1901 norm of the inverse of `x` [1]_; the norm can be the usual L2-norm 

1902 (root-of-sum-of-squares) or one of a number of other matrix norms. 

1903 

1904 References 

1905 ---------- 

1906 .. [1] G. Strang, *Linear Algebra and Its Applications*, Orlando, FL, 

1907 Academic Press, Inc., 1980, pg. 285. 

1908 

1909 Examples 

1910 -------- 

1911 >>> from numpy import linalg as LA 

1912 >>> a = np.array([[1, 0, -1], [0, 1, 0], [1, 0, 1]]) 

1913 >>> a 

1914 array([[ 1, 0, -1], 

1915 [ 0, 1, 0], 

1916 [ 1, 0, 1]]) 

1917 >>> LA.cond(a) 

1918 1.4142135623730951 

1919 >>> LA.cond(a, 'fro') 

1920 3.1622776601683795 

1921 >>> LA.cond(a, np.inf) 

1922 2.0 

1923 >>> LA.cond(a, -np.inf) 

1924 1.0 

1925 >>> LA.cond(a, 1) 

1926 2.0 

1927 >>> LA.cond(a, -1) 

1928 1.0 

1929 >>> LA.cond(a, 2) 

1930 1.4142135623730951 

1931 >>> LA.cond(a, -2) 

1932 0.70710678118654746 # may vary 

1933 >>> (min(LA.svd(a, compute_uv=False)) * 

1934 ... min(LA.svd(LA.inv(a), compute_uv=False))) 

1935 0.70710678118654746 # may vary 

1936 

1937 """ 

1938 x = asarray(x) # in case we have a matrix 

1939 if _is_empty_2d(x): 

1940 raise LinAlgError("cond is not defined on empty arrays") 

1941 if p is None or p == 2 or p == -2: 

1942 s = svd(x, compute_uv=False) 

1943 with errstate(all='ignore'): 

1944 if p == -2: 

1945 r = s[..., -1] / s[..., 0] 

1946 else: 

1947 r = s[..., 0] / s[..., -1] 

1948 else: 

1949 # Call inv(x) ignoring errors. The result array will 

1950 # contain nans in the entries where inversion failed. 

1951 _assert_stacked_2d(x) 

1952 _assert_stacked_square(x) 

1953 t, result_t = _commonType(x) 

1954 signature = 'D->D' if isComplexType(t) else 'd->d' 

1955 with errstate(all='ignore'): 

1956 invx = _umath_linalg.inv(x, signature=signature) 

1957 r = norm(x, p, axis=(-2, -1)) * norm(invx, p, axis=(-2, -1)) 

1958 r = r.astype(result_t, copy=False) 

1959 

1960 # Convert nans to infs unless the original array had nan entries 

1961 r = asarray(r) 

1962 nan_mask = isnan(r) 

1963 if nan_mask.any(): 

1964 nan_mask &= ~isnan(x).any(axis=(-2, -1)) 

1965 if r.ndim > 0: 

1966 r[nan_mask] = inf 

1967 elif nan_mask: 

1968 r[()] = inf 

1969 

1970 # Convention is to return scalars instead of 0d arrays 

1971 if r.ndim == 0: 

1972 r = r[()] 

1973 

1974 return r 

1975 

1976 

1977def _matrix_rank_dispatcher(A, tol=None, hermitian=None, *, rtol=None): 

1978 return (A,) 

1979 

1980 

1981@array_function_dispatch(_matrix_rank_dispatcher) 

1982def matrix_rank(A, tol=None, hermitian=False, *, rtol=None): 

1983 """ 

1984 Return matrix rank of array using SVD method 

1985 

1986 Rank of the array is the number of singular values of the array that are 

1987 greater than `tol`. 

1988 

1989 .. versionchanged:: 1.14 

1990 Can now operate on stacks of matrices 

1991 

1992 Parameters 

1993 ---------- 

1994 A : {(M,), (..., M, N)} array_like 

1995 Input vector or stack of matrices. 

1996 tol : (...) array_like, float, optional 

1997 Threshold below which SVD values are considered zero. If `tol` is 

1998 None, and ``S`` is an array with singular values for `M`, and 

1999 ``eps`` is the epsilon value for datatype of ``S``, then `tol` is 

2000 set to ``S.max() * max(M, N) * eps``. 

2001 

2002 .. versionchanged:: 1.14 

2003 Broadcasted against the stack of matrices 

2004 hermitian : bool, optional 

2005 If True, `A` is assumed to be Hermitian (symmetric if real-valued), 

2006 enabling a more efficient method for finding singular values. 

2007 Defaults to False. 

2008 

2009 .. versionadded:: 1.14 

2010 rtol : (...) array_like, float, optional 

2011 Parameter for the relative tolerance component. Only ``tol`` or 

2012 ``rtol`` can be set at a time. Defaults to ``max(M, N) * eps``. 

2013 

2014 .. versionadded:: 2.0.0 

2015 

2016 Returns 

2017 ------- 

2018 rank : (...) array_like 

2019 Rank of A. 

2020 

2021 Notes 

2022 ----- 

2023 The default threshold to detect rank deficiency is a test on the magnitude 

2024 of the singular values of `A`. By default, we identify singular values 

2025 less than ``S.max() * max(M, N) * eps`` as indicating rank deficiency 

2026 (with the symbols defined above). This is the algorithm MATLAB uses [1]. 

2027 It also appears in *Numerical recipes* in the discussion of SVD solutions 

2028 for linear least squares [2]. 

2029 

2030 This default threshold is designed to detect rank deficiency accounting 

2031 for the numerical errors of the SVD computation. Imagine that there 

2032 is a column in `A` that is an exact (in floating point) linear combination 

2033 of other columns in `A`. Computing the SVD on `A` will not produce 

2034 a singular value exactly equal to 0 in general: any difference of 

2035 the smallest SVD value from 0 will be caused by numerical imprecision 

2036 in the calculation of the SVD. Our threshold for small SVD values takes 

2037 this numerical imprecision into account, and the default threshold will 

2038 detect such numerical rank deficiency. The threshold may declare a matrix 

2039 `A` rank deficient even if the linear combination of some columns of `A` 

2040 is not exactly equal to another column of `A` but only numerically very 

2041 close to another column of `A`. 

2042 

2043 We chose our default threshold because it is in wide use. Other thresholds 

2044 are possible. For example, elsewhere in the 2007 edition of *Numerical 

2045 recipes* there is an alternative threshold of ``S.max() * 

2046 np.finfo(A.dtype).eps / 2. * np.sqrt(m + n + 1.)``. The authors describe 

2047 this threshold as being based on "expected roundoff error" (p 71). 

2048 

2049 The thresholds above deal with floating point roundoff error in the 

2050 calculation of the SVD. However, you may have more information about 

2051 the sources of error in `A` that would make you consider other tolerance 

2052 values to detect *effective* rank deficiency. The most useful measure 

2053 of the tolerance depends on the operations you intend to use on your 

2054 matrix. For example, if your data come from uncertain measurements with 

2055 uncertainties greater than floating point epsilon, choosing a tolerance 

2056 near that uncertainty may be preferable. The tolerance may be absolute 

2057 if the uncertainties are absolute rather than relative. 

2058 

2059 References 

2060 ---------- 

2061 .. [1] MATLAB reference documentation, "Rank" 

2062 https://www.mathworks.com/help/techdoc/ref/rank.html 

2063 .. [2] W. H. Press, S. A. Teukolsky, W. T. Vetterling and B. P. Flannery, 

2064 "Numerical Recipes (3rd edition)", Cambridge University Press, 2007, 

2065 page 795. 

2066 

2067 Examples 

2068 -------- 

2069 >>> from numpy.linalg import matrix_rank 

2070 >>> matrix_rank(np.eye(4)) # Full rank matrix 

2071 4 

2072 >>> I=np.eye(4); I[-1,-1] = 0. # rank deficient matrix 

2073 >>> matrix_rank(I) 

2074 3 

2075 >>> matrix_rank(np.ones((4,))) # 1 dimension - rank 1 unless all 0 

2076 1 

2077 >>> matrix_rank(np.zeros((4,))) 

2078 0 

2079 """ 

2080 if rtol is not None and tol is not None: 

2081 raise ValueError("`tol` and `rtol` can't be both set.") 

2082 

2083 A = asarray(A) 

2084 if A.ndim < 2: 

2085 return int(not all(A == 0)) 

2086 S = svd(A, compute_uv=False, hermitian=hermitian) 

2087 

2088 if tol is None: 

2089 if rtol is None: 

2090 rtol = max(A.shape[-2:]) * finfo(S.dtype).eps 

2091 else: 

2092 rtol = asarray(rtol)[..., newaxis] 

2093 tol = S.max(axis=-1, keepdims=True) * rtol 

2094 else: 

2095 tol = asarray(tol)[..., newaxis] 

2096 

2097 return count_nonzero(S > tol, axis=-1) 

2098 

2099 

2100# Generalized inverse 

2101 

2102def _pinv_dispatcher(a, rcond=None, hermitian=None, *, rtol=None): 

2103 return (a,) 

2104 

2105 

2106@array_function_dispatch(_pinv_dispatcher) 

2107def pinv(a, rcond=None, hermitian=False, *, rtol=_NoValue): 

2108 """ 

2109 Compute the (Moore-Penrose) pseudo-inverse of a matrix. 

2110 

2111 Calculate the generalized inverse of a matrix using its 

2112 singular-value decomposition (SVD) and including all 

2113 *large* singular values. 

2114 

2115 .. versionchanged:: 1.14 

2116 Can now operate on stacks of matrices 

2117 

2118 Parameters 

2119 ---------- 

2120 a : (..., M, N) array_like 

2121 Matrix or stack of matrices to be pseudo-inverted. 

2122 rcond : (...) array_like of float, optional 

2123 Cutoff for small singular values. 

2124 Singular values less than or equal to 

2125 ``rcond * largest_singular_value`` are set to zero. 

2126 Broadcasts against the stack of matrices. Default: ``1e-15``. 

2127 hermitian : bool, optional 

2128 If True, `a` is assumed to be Hermitian (symmetric if real-valued), 

2129 enabling a more efficient method for finding singular values. 

2130 Defaults to False. 

2131 

2132 .. versionadded:: 1.17.0 

2133 rtol : (...) array_like of float, optional 

2134 Same as `rcond`, but it's an Array API compatible parameter name. 

2135 Only `rcond` or `rtol` can be set at a time. If none of them are 

2136 provided then NumPy's ``1e-15`` default is used. If ``rtol=None`` 

2137 is passed then the API standard default is used. 

2138 

2139 .. versionadded:: 2.0.0 

2140 

2141 Returns 

2142 ------- 

2143 B : (..., N, M) ndarray 

2144 The pseudo-inverse of `a`. If `a` is a `matrix` instance, then so 

2145 is `B`. 

2146 

2147 Raises 

2148 ------ 

2149 LinAlgError 

2150 If the SVD computation does not converge. 

2151 

2152 See Also 

2153 -------- 

2154 scipy.linalg.pinv : Similar function in SciPy. 

2155 scipy.linalg.pinvh : Compute the (Moore-Penrose) pseudo-inverse of a 

2156 Hermitian matrix. 

2157 

2158 Notes 

2159 ----- 

2160 The pseudo-inverse of a matrix A, denoted :math:`A^+`, is 

2161 defined as: "the matrix that 'solves' [the least-squares problem] 

2162 :math:`Ax = b`," i.e., if :math:`\\bar{x}` is said solution, then 

2163 :math:`A^+` is that matrix such that :math:`\\bar{x} = A^+b`. 

2164 

2165 It can be shown that if :math:`Q_1 \\Sigma Q_2^T = A` is the singular 

2166 value decomposition of A, then 

2167 :math:`A^+ = Q_2 \\Sigma^+ Q_1^T`, where :math:`Q_{1,2}` are 

2168 orthogonal matrices, :math:`\\Sigma` is a diagonal matrix consisting 

2169 of A's so-called singular values, (followed, typically, by 

2170 zeros), and then :math:`\\Sigma^+` is simply the diagonal matrix 

2171 consisting of the reciprocals of A's singular values 

2172 (again, followed by zeros). [1]_ 

2173 

2174 References 

2175 ---------- 

2176 .. [1] G. Strang, *Linear Algebra and Its Applications*, 2nd Ed., Orlando, 

2177 FL, Academic Press, Inc., 1980, pp. 139-142. 

2178 

2179 Examples 

2180 -------- 

2181 The following example checks that ``a * a+ * a == a`` and 

2182 ``a+ * a * a+ == a+``: 

2183 

2184 >>> a = np.random.randn(9, 6) 

2185 >>> B = np.linalg.pinv(a) 

2186 >>> np.allclose(a, np.dot(a, np.dot(B, a))) 

2187 True 

2188 >>> np.allclose(B, np.dot(B, np.dot(a, B))) 

2189 True 

2190 

2191 """ 

2192 a, wrap = _makearray(a) 

2193 if rcond is None: 

2194 if rtol is _NoValue: 

2195 rcond = 1e-15 

2196 elif rtol is None: 

2197 rcond = max(a.shape[-2:]) * finfo(a.dtype).eps 

2198 else: 

2199 rcond = rtol 

2200 elif rtol is not _NoValue: 

2201 raise ValueError("`rtol` and `rcond` can't be both set.") 

2202 else: 

2203 # NOTE: Deprecate `rcond` in a few versions. 

2204 pass 

2205 

2206 rcond = asarray(rcond) 

2207 if _is_empty_2d(a): 

2208 m, n = a.shape[-2:] 

2209 res = empty(a.shape[:-2] + (n, m), dtype=a.dtype) 

2210 return wrap(res) 

2211 a = a.conjugate() 

2212 u, s, vt = svd(a, full_matrices=False, hermitian=hermitian) 

2213 

2214 # discard small singular values 

2215 cutoff = rcond[..., newaxis] * amax(s, axis=-1, keepdims=True) 

2216 large = s > cutoff 

2217 s = divide(1, s, where=large, out=s) 

2218 s[~large] = 0 

2219 

2220 res = matmul(transpose(vt), multiply(s[..., newaxis], transpose(u))) 

2221 return wrap(res) 

2222 

2223 

2224# Determinant 

2225 

2226 

2227@array_function_dispatch(_unary_dispatcher) 

2228def slogdet(a): 

2229 """ 

2230 Compute the sign and (natural) logarithm of the determinant of an array. 

2231 

2232 If an array has a very small or very large determinant, then a call to 

2233 `det` may overflow or underflow. This routine is more robust against such 

2234 issues, because it computes the logarithm of the determinant rather than 

2235 the determinant itself. 

2236 

2237 Parameters 

2238 ---------- 

2239 a : (..., M, M) array_like 

2240 Input array, has to be a square 2-D array. 

2241 

2242 Returns 

2243 ------- 

2244 A namedtuple with the following attributes: 

2245 

2246 sign : (...) array_like 

2247 A number representing the sign of the determinant. For a real matrix, 

2248 this is 1, 0, or -1. For a complex matrix, this is a complex number 

2249 with absolute value 1 (i.e., it is on the unit circle), or else 0. 

2250 logabsdet : (...) array_like 

2251 The natural log of the absolute value of the determinant. 

2252 

2253 If the determinant is zero, then `sign` will be 0 and `logabsdet` 

2254 will be -inf. In all cases, the determinant is equal to 

2255 ``sign * np.exp(logabsdet)``. 

2256 

2257 See Also 

2258 -------- 

2259 det 

2260 

2261 Notes 

2262 ----- 

2263 

2264 .. versionadded:: 1.8.0 

2265 

2266 Broadcasting rules apply, see the `numpy.linalg` documentation for 

2267 details. 

2268 

2269 .. versionadded:: 1.6.0 

2270 

2271 The determinant is computed via LU factorization using the LAPACK 

2272 routine ``z/dgetrf``. 

2273 

2274 

2275 Examples 

2276 -------- 

2277 The determinant of a 2-D array ``[[a, b], [c, d]]`` is ``ad - bc``: 

2278 

2279 >>> a = np.array([[1, 2], [3, 4]]) 

2280 >>> (sign, logabsdet) = np.linalg.slogdet(a) 

2281 >>> (sign, logabsdet) 

2282 (-1, 0.69314718055994529) # may vary 

2283 >>> sign * np.exp(logabsdet) 

2284 -2.0 

2285 

2286 Computing log-determinants for a stack of matrices: 

2287 

2288 >>> a = np.array([ [[1, 2], [3, 4]], [[1, 2], [2, 1]], [[1, 3], [3, 1]] ]) 

2289 >>> a.shape 

2290 (3, 2, 2) 

2291 >>> sign, logabsdet = np.linalg.slogdet(a) 

2292 >>> (sign, logabsdet) 

2293 (array([-1., -1., -1.]), array([ 0.69314718, 1.09861229, 2.07944154])) 

2294 >>> sign * np.exp(logabsdet) 

2295 array([-2., -3., -8.]) 

2296 

2297 This routine succeeds where ordinary `det` does not: 

2298 

2299 >>> np.linalg.det(np.eye(500) * 0.1) 

2300 0.0 

2301 >>> np.linalg.slogdet(np.eye(500) * 0.1) 

2302 (1, -1151.2925464970228) 

2303 

2304 """ 

2305 a = asarray(a) 

2306 _assert_stacked_2d(a) 

2307 _assert_stacked_square(a) 

2308 t, result_t = _commonType(a) 

2309 real_t = _realType(result_t) 

2310 signature = 'D->Dd' if isComplexType(t) else 'd->dd' 

2311 sign, logdet = _umath_linalg.slogdet(a, signature=signature) 

2312 sign = sign.astype(result_t, copy=False) 

2313 logdet = logdet.astype(real_t, copy=False) 

2314 return SlogdetResult(sign, logdet) 

2315 

2316 

2317@array_function_dispatch(_unary_dispatcher) 

2318def det(a): 

2319 """ 

2320 Compute the determinant of an array. 

2321 

2322 Parameters 

2323 ---------- 

2324 a : (..., M, M) array_like 

2325 Input array to compute determinants for. 

2326 

2327 Returns 

2328 ------- 

2329 det : (...) array_like 

2330 Determinant of `a`. 

2331 

2332 See Also 

2333 -------- 

2334 slogdet : Another way to represent the determinant, more suitable 

2335 for large matrices where underflow/overflow may occur. 

2336 scipy.linalg.det : Similar function in SciPy. 

2337 

2338 Notes 

2339 ----- 

2340 

2341 .. versionadded:: 1.8.0 

2342 

2343 Broadcasting rules apply, see the `numpy.linalg` documentation for 

2344 details. 

2345 

2346 The determinant is computed via LU factorization using the LAPACK 

2347 routine ``z/dgetrf``. 

2348 

2349 Examples 

2350 -------- 

2351 The determinant of a 2-D array [[a, b], [c, d]] is ad - bc: 

2352 

2353 >>> a = np.array([[1, 2], [3, 4]]) 

2354 >>> np.linalg.det(a) 

2355 -2.0 # may vary 

2356 

2357 Computing determinants for a stack of matrices: 

2358 

2359 >>> a = np.array([ [[1, 2], [3, 4]], [[1, 2], [2, 1]], [[1, 3], [3, 1]] ]) 

2360 >>> a.shape 

2361 (3, 2, 2) 

2362 >>> np.linalg.det(a) 

2363 array([-2., -3., -8.]) 

2364 

2365 """ 

2366 a = asarray(a) 

2367 _assert_stacked_2d(a) 

2368 _assert_stacked_square(a) 

2369 t, result_t = _commonType(a) 

2370 signature = 'D->D' if isComplexType(t) else 'd->d' 

2371 r = _umath_linalg.det(a, signature=signature) 

2372 r = r.astype(result_t, copy=False) 

2373 return r 

2374 

2375 

2376# Linear Least Squares 

2377 

2378def _lstsq_dispatcher(a, b, rcond=None): 

2379 return (a, b) 

2380 

2381 

2382@array_function_dispatch(_lstsq_dispatcher) 

2383def lstsq(a, b, rcond=None): 

2384 r""" 

2385 Return the least-squares solution to a linear matrix equation. 

2386 

2387 Computes the vector `x` that approximately solves the equation 

2388 ``a @ x = b``. The equation may be under-, well-, or over-determined 

2389 (i.e., the number of linearly independent rows of `a` can be less than, 

2390 equal to, or greater than its number of linearly independent columns). 

2391 If `a` is square and of full rank, then `x` (but for round-off error) 

2392 is the "exact" solution of the equation. Else, `x` minimizes the 

2393 Euclidean 2-norm :math:`||b - ax||`. If there are multiple minimizing 

2394 solutions, the one with the smallest 2-norm :math:`||x||` is returned. 

2395 

2396 Parameters 

2397 ---------- 

2398 a : (M, N) array_like 

2399 "Coefficient" matrix. 

2400 b : {(M,), (M, K)} array_like 

2401 Ordinate or "dependent variable" values. If `b` is two-dimensional, 

2402 the least-squares solution is calculated for each of the `K` columns 

2403 of `b`. 

2404 rcond : float, optional 

2405 Cut-off ratio for small singular values of `a`. 

2406 For the purposes of rank determination, singular values are treated 

2407 as zero if they are smaller than `rcond` times the largest singular 

2408 value of `a`. 

2409 The default uses the machine precision times ``max(M, N)``. Passing 

2410 ``-1`` will use machine precision. 

2411 

2412 .. versionchanged:: 2.0 

2413 Previously, the default was ``-1``, but a warning was given that 

2414 this would change. 

2415 

2416 Returns 

2417 ------- 

2418 x : {(N,), (N, K)} ndarray 

2419 Least-squares solution. If `b` is two-dimensional, 

2420 the solutions are in the `K` columns of `x`. 

2421 residuals : {(1,), (K,), (0,)} ndarray 

2422 Sums of squared residuals: Squared Euclidean 2-norm for each column in 

2423 ``b - a @ x``. 

2424 If the rank of `a` is < N or M <= N, this is an empty array. 

2425 If `b` is 1-dimensional, this is a (1,) shape array. 

2426 Otherwise the shape is (K,). 

2427 rank : int 

2428 Rank of matrix `a`. 

2429 s : (min(M, N),) ndarray 

2430 Singular values of `a`. 

2431 

2432 Raises 

2433 ------ 

2434 LinAlgError 

2435 If computation does not converge. 

2436 

2437 See Also 

2438 -------- 

2439 scipy.linalg.lstsq : Similar function in SciPy. 

2440 

2441 Notes 

2442 ----- 

2443 If `b` is a matrix, then all array results are returned as matrices. 

2444 

2445 Examples 

2446 -------- 

2447 Fit a line, ``y = mx + c``, through some noisy data-points: 

2448 

2449 >>> x = np.array([0, 1, 2, 3]) 

2450 >>> y = np.array([-1, 0.2, 0.9, 2.1]) 

2451 

2452 By examining the coefficients, we see that the line should have a 

2453 gradient of roughly 1 and cut the y-axis at, more or less, -1. 

2454 

2455 We can rewrite the line equation as ``y = Ap``, where ``A = [[x 1]]`` 

2456 and ``p = [[m], [c]]``. Now use `lstsq` to solve for `p`: 

2457 

2458 >>> A = np.vstack([x, np.ones(len(x))]).T 

2459 >>> A 

2460 array([[ 0., 1.], 

2461 [ 1., 1.], 

2462 [ 2., 1.], 

2463 [ 3., 1.]]) 

2464 

2465 >>> m, c = np.linalg.lstsq(A, y)[0] 

2466 >>> m, c 

2467 (1.0 -0.95) # may vary 

2468 

2469 Plot the data along with the fitted line: 

2470 

2471 >>> import matplotlib.pyplot as plt 

2472 >>> _ = plt.plot(x, y, 'o', label='Original data', markersize=10) 

2473 >>> _ = plt.plot(x, m*x + c, 'r', label='Fitted line') 

2474 >>> _ = plt.legend() 

2475 >>> plt.show() 

2476 

2477 """ 

2478 a, _ = _makearray(a) 

2479 b, wrap = _makearray(b) 

2480 is_1d = b.ndim == 1 

2481 if is_1d: 

2482 b = b[:, newaxis] 

2483 _assert_2d(a, b) 

2484 m, n = a.shape[-2:] 

2485 m2, n_rhs = b.shape[-2:] 

2486 if m != m2: 

2487 raise LinAlgError('Incompatible dimensions') 

2488 

2489 t, result_t = _commonType(a, b) 

2490 result_real_t = _realType(result_t) 

2491 

2492 if rcond is None: 

2493 rcond = finfo(t).eps * max(n, m) 

2494 

2495 if m <= n: 

2496 gufunc = _umath_linalg.lstsq_m 

2497 else: 

2498 gufunc = _umath_linalg.lstsq_n 

2499 

2500 signature = 'DDd->Ddid' if isComplexType(t) else 'ddd->ddid' 

2501 if n_rhs == 0: 

2502 # lapack can't handle n_rhs = 0 - so allocate 

2503 # the array one larger in that axis 

2504 b = zeros(b.shape[:-2] + (m, n_rhs + 1), dtype=b.dtype) 

2505 

2506 with errstate(call=_raise_linalgerror_lstsq, invalid='call', 

2507 over='ignore', divide='ignore', under='ignore'): 

2508 x, resids, rank, s = gufunc(a, b, rcond, signature=signature) 

2509 if m == 0: 

2510 x[...] = 0 

2511 if n_rhs == 0: 

2512 # remove the item we added 

2513 x = x[..., :n_rhs] 

2514 resids = resids[..., :n_rhs] 

2515 

2516 # remove the axis we added 

2517 if is_1d: 

2518 x = x.squeeze(axis=-1) 

2519 # we probably should squeeze resids too, but we can't 

2520 # without breaking compatibility. 

2521 

2522 # as documented 

2523 if rank != n or m <= n: 

2524 resids = array([], result_real_t) 

2525 

2526 # coerce output arrays 

2527 s = s.astype(result_real_t, copy=False) 

2528 resids = resids.astype(result_real_t, copy=False) 

2529 # Copying lets the memory in r_parts be freed 

2530 x = x.astype(result_t, copy=True) 

2531 return wrap(x), wrap(resids), rank, s 

2532 

2533 

2534def _multi_svd_norm(x, row_axis, col_axis, op): 

2535 """Compute a function of the singular values of the 2-D matrices in `x`. 

2536 

2537 This is a private utility function used by `numpy.linalg.norm()`. 

2538 

2539 Parameters 

2540 ---------- 

2541 x : ndarray 

2542 row_axis, col_axis : int 

2543 The axes of `x` that hold the 2-D matrices. 

2544 op : callable 

2545 This should be either numpy.amin or `numpy.amax` or `numpy.sum`. 

2546 

2547 Returns 

2548 ------- 

2549 result : float or ndarray 

2550 If `x` is 2-D, the return values is a float. 

2551 Otherwise, it is an array with ``x.ndim - 2`` dimensions. 

2552 The return values are either the minimum or maximum or sum of the 

2553 singular values of the matrices, depending on whether `op` 

2554 is `numpy.amin` or `numpy.amax` or `numpy.sum`. 

2555 

2556 """ 

2557 y = moveaxis(x, (row_axis, col_axis), (-2, -1)) 

2558 result = op(svd(y, compute_uv=False), axis=-1) 

2559 return result 

2560 

2561 

2562def _norm_dispatcher(x, ord=None, axis=None, keepdims=None): 

2563 return (x,) 

2564 

2565 

2566@array_function_dispatch(_norm_dispatcher) 

2567def norm(x, ord=None, axis=None, keepdims=False): 

2568 """ 

2569 Matrix or vector norm. 

2570 

2571 This function is able to return one of eight different matrix norms, 

2572 or one of an infinite number of vector norms (described below), depending 

2573 on the value of the ``ord`` parameter. 

2574 

2575 Parameters 

2576 ---------- 

2577 x : array_like 

2578 Input array. If `axis` is None, `x` must be 1-D or 2-D, unless `ord` 

2579 is None. If both `axis` and `ord` are None, the 2-norm of 

2580 ``x.ravel`` will be returned. 

2581 ord : {non-zero int, inf, -inf, 'fro', 'nuc'}, optional 

2582 Order of the norm (see table under ``Notes``). inf means numpy's 

2583 `inf` object. The default is None. 

2584 axis : {None, int, 2-tuple of ints}, optional. 

2585 If `axis` is an integer, it specifies the axis of `x` along which to 

2586 compute the vector norms. If `axis` is a 2-tuple, it specifies the 

2587 axes that hold 2-D matrices, and the matrix norms of these matrices 

2588 are computed. If `axis` is None then either a vector norm (when `x` 

2589 is 1-D) or a matrix norm (when `x` is 2-D) is returned. The default 

2590 is None. 

2591 

2592 .. versionadded:: 1.8.0 

2593 

2594 keepdims : bool, optional 

2595 If this is set to True, the axes which are normed over are left in the 

2596 result as dimensions with size one. With this option the result will 

2597 broadcast correctly against the original `x`. 

2598 

2599 .. versionadded:: 1.10.0 

2600 

2601 Returns 

2602 ------- 

2603 n : float or ndarray 

2604 Norm of the matrix or vector(s). 

2605 

2606 See Also 

2607 -------- 

2608 scipy.linalg.norm : Similar function in SciPy. 

2609 

2610 Notes 

2611 ----- 

2612 For values of ``ord < 1``, the result is, strictly speaking, not a 

2613 mathematical 'norm', but it may still be useful for various numerical 

2614 purposes. 

2615 

2616 The following norms can be calculated: 

2617 

2618 ===== ============================ ========================== 

2619 ord norm for matrices norm for vectors 

2620 ===== ============================ ========================== 

2621 None Frobenius norm 2-norm 

2622 'fro' Frobenius norm -- 

2623 'nuc' nuclear norm -- 

2624 inf max(sum(abs(x), axis=1)) max(abs(x)) 

2625 -inf min(sum(abs(x), axis=1)) min(abs(x)) 

2626 0 -- sum(x != 0) 

2627 1 max(sum(abs(x), axis=0)) as below 

2628 -1 min(sum(abs(x), axis=0)) as below 

2629 2 2-norm (largest sing. value) as below 

2630 -2 smallest singular value as below 

2631 other -- sum(abs(x)**ord)**(1./ord) 

2632 ===== ============================ ========================== 

2633 

2634 The Frobenius norm is given by [1]_: 

2635 

2636 :math:`||A||_F = [\\sum_{i,j} abs(a_{i,j})^2]^{1/2}` 

2637 

2638 The nuclear norm is the sum of the singular values. 

2639 

2640 Both the Frobenius and nuclear norm orders are only defined for 

2641 matrices and raise a ValueError when ``x.ndim != 2``. 

2642 

2643 References 

2644 ---------- 

2645 .. [1] G. H. Golub and C. F. Van Loan, *Matrix Computations*, 

2646 Baltimore, MD, Johns Hopkins University Press, 1985, pg. 15 

2647 

2648 Examples 

2649 -------- 

2650 >>> from numpy import linalg as LA 

2651 >>> a = np.arange(9) - 4 

2652 >>> a 

2653 array([-4, -3, -2, ..., 2, 3, 4]) 

2654 >>> b = a.reshape((3, 3)) 

2655 >>> b 

2656 array([[-4, -3, -2], 

2657 [-1, 0, 1], 

2658 [ 2, 3, 4]]) 

2659 

2660 >>> LA.norm(a) 

2661 7.745966692414834 

2662 >>> LA.norm(b) 

2663 7.745966692414834 

2664 >>> LA.norm(b, 'fro') 

2665 7.745966692414834 

2666 >>> LA.norm(a, np.inf) 

2667 4.0 

2668 >>> LA.norm(b, np.inf) 

2669 9.0 

2670 >>> LA.norm(a, -np.inf) 

2671 0.0 

2672 >>> LA.norm(b, -np.inf) 

2673 2.0 

2674 

2675 >>> LA.norm(a, 1) 

2676 20.0 

2677 >>> LA.norm(b, 1) 

2678 7.0 

2679 >>> LA.norm(a, -1) 

2680 -4.6566128774142013e-010 

2681 >>> LA.norm(b, -1) 

2682 6.0 

2683 >>> LA.norm(a, 2) 

2684 7.745966692414834 

2685 >>> LA.norm(b, 2) 

2686 7.3484692283495345 

2687 

2688 >>> LA.norm(a, -2) 

2689 0.0 

2690 >>> LA.norm(b, -2) 

2691 1.8570331885190563e-016 # may vary 

2692 >>> LA.norm(a, 3) 

2693 5.8480354764257312 # may vary 

2694 >>> LA.norm(a, -3) 

2695 0.0 

2696 

2697 Using the `axis` argument to compute vector norms: 

2698 

2699 >>> c = np.array([[ 1, 2, 3], 

2700 ... [-1, 1, 4]]) 

2701 >>> LA.norm(c, axis=0) 

2702 array([ 1.41421356, 2.23606798, 5. ]) 

2703 >>> LA.norm(c, axis=1) 

2704 array([ 3.74165739, 4.24264069]) 

2705 >>> LA.norm(c, ord=1, axis=1) 

2706 array([ 6., 6.]) 

2707 

2708 Using the `axis` argument to compute matrix norms: 

2709 

2710 >>> m = np.arange(8).reshape(2,2,2) 

2711 >>> LA.norm(m, axis=(1,2)) 

2712 array([ 3.74165739, 11.22497216]) 

2713 >>> LA.norm(m[0, :, :]), LA.norm(m[1, :, :]) 

2714 (3.7416573867739413, 11.224972160321824) 

2715 

2716 """ 

2717 x = asarray(x) 

2718 

2719 if not issubclass(x.dtype.type, (inexact, object_)): 

2720 x = x.astype(float) 

2721 

2722 # Immediately handle some default, simple, fast, and common cases. 

2723 if axis is None: 

2724 ndim = x.ndim 

2725 if ( 

2726 (ord is None) or 

2727 (ord in ('f', 'fro') and ndim == 2) or 

2728 (ord == 2 and ndim == 1) 

2729 ): 

2730 x = x.ravel(order='K') 

2731 if isComplexType(x.dtype.type): 

2732 x_real = x.real 

2733 x_imag = x.imag 

2734 sqnorm = x_real.dot(x_real) + x_imag.dot(x_imag) 

2735 else: 

2736 sqnorm = x.dot(x) 

2737 ret = sqrt(sqnorm) 

2738 if keepdims: 

2739 ret = ret.reshape(ndim*[1]) 

2740 return ret 

2741 

2742 # Normalize the `axis` argument to a tuple. 

2743 nd = x.ndim 

2744 if axis is None: 

2745 axis = tuple(range(nd)) 

2746 elif not isinstance(axis, tuple): 

2747 try: 

2748 axis = int(axis) 

2749 except Exception as e: 

2750 raise TypeError( 

2751 "'axis' must be None, an integer or a tuple of integers" 

2752 ) from e 

2753 axis = (axis,) 

2754 

2755 if len(axis) == 1: 

2756 if ord == inf: 

2757 return abs(x).max(axis=axis, keepdims=keepdims) 

2758 elif ord == -inf: 

2759 return abs(x).min(axis=axis, keepdims=keepdims) 

2760 elif ord == 0: 

2761 # Zero norm 

2762 return ( 

2763 (x != 0) 

2764 .astype(x.real.dtype) 

2765 .sum(axis=axis, keepdims=keepdims) 

2766 ) 

2767 elif ord == 1: 

2768 # special case for speedup 

2769 return add.reduce(abs(x), axis=axis, keepdims=keepdims) 

2770 elif ord is None or ord == 2: 

2771 # special case for speedup 

2772 s = (x.conj() * x).real 

2773 return sqrt(add.reduce(s, axis=axis, keepdims=keepdims)) 

2774 # None of the str-type keywords for ord ('fro', 'nuc') 

2775 # are valid for vectors 

2776 elif isinstance(ord, str): 

2777 raise ValueError(f"Invalid norm order '{ord}' for vectors") 

2778 else: 

2779 absx = abs(x) 

2780 absx **= ord 

2781 ret = add.reduce(absx, axis=axis, keepdims=keepdims) 

2782 ret **= reciprocal(ord, dtype=ret.dtype) 

2783 return ret 

2784 elif len(axis) == 2: 

2785 row_axis, col_axis = axis 

2786 row_axis = normalize_axis_index(row_axis, nd) 

2787 col_axis = normalize_axis_index(col_axis, nd) 

2788 if row_axis == col_axis: 

2789 raise ValueError('Duplicate axes given.') 

2790 if ord == 2: 

2791 ret = _multi_svd_norm(x, row_axis, col_axis, amax) 

2792 elif ord == -2: 

2793 ret = _multi_svd_norm(x, row_axis, col_axis, amin) 

2794 elif ord == 1: 

2795 if col_axis > row_axis: 

2796 col_axis -= 1 

2797 ret = add.reduce(abs(x), axis=row_axis).max(axis=col_axis) 

2798 elif ord == inf: 

2799 if row_axis > col_axis: 

2800 row_axis -= 1 

2801 ret = add.reduce(abs(x), axis=col_axis).max(axis=row_axis) 

2802 elif ord == -1: 

2803 if col_axis > row_axis: 

2804 col_axis -= 1 

2805 ret = add.reduce(abs(x), axis=row_axis).min(axis=col_axis) 

2806 elif ord == -inf: 

2807 if row_axis > col_axis: 

2808 row_axis -= 1 

2809 ret = add.reduce(abs(x), axis=col_axis).min(axis=row_axis) 

2810 elif ord in [None, 'fro', 'f']: 

2811 ret = sqrt(add.reduce((x.conj() * x).real, axis=axis)) 

2812 elif ord == 'nuc': 

2813 ret = _multi_svd_norm(x, row_axis, col_axis, sum) 

2814 else: 

2815 raise ValueError("Invalid norm order for matrices.") 

2816 if keepdims: 

2817 ret_shape = list(x.shape) 

2818 ret_shape[axis[0]] = 1 

2819 ret_shape[axis[1]] = 1 

2820 ret = ret.reshape(ret_shape) 

2821 return ret 

2822 else: 

2823 raise ValueError("Improper number of dimensions to norm.") 

2824 

2825 

2826# multi_dot 

2827 

2828def _multidot_dispatcher(arrays, *, out=None): 

2829 yield from arrays 

2830 yield out 

2831 

2832 

2833@array_function_dispatch(_multidot_dispatcher) 

2834def multi_dot(arrays, *, out=None): 

2835 """ 

2836 Compute the dot product of two or more arrays in a single function call, 

2837 while automatically selecting the fastest evaluation order. 

2838 

2839 `multi_dot` chains `numpy.dot` and uses optimal parenthesization 

2840 of the matrices [1]_ [2]_. Depending on the shapes of the matrices, 

2841 this can speed up the multiplication a lot. 

2842 

2843 If the first argument is 1-D it is treated as a row vector. 

2844 If the last argument is 1-D it is treated as a column vector. 

2845 The other arguments must be 2-D. 

2846 

2847 Think of `multi_dot` as:: 

2848 

2849 def multi_dot(arrays): return functools.reduce(np.dot, arrays) 

2850 

2851 

2852 Parameters 

2853 ---------- 

2854 arrays : sequence of array_like 

2855 If the first argument is 1-D it is treated as row vector. 

2856 If the last argument is 1-D it is treated as column vector. 

2857 The other arguments must be 2-D. 

2858 out : ndarray, optional 

2859 Output argument. This must have the exact kind that would be returned 

2860 if it was not used. In particular, it must have the right type, must be 

2861 C-contiguous, and its dtype must be the dtype that would be returned 

2862 for `dot(a, b)`. This is a performance feature. Therefore, if these 

2863 conditions are not met, an exception is raised, instead of attempting 

2864 to be flexible. 

2865 

2866 .. versionadded:: 1.19.0 

2867 

2868 Returns 

2869 ------- 

2870 output : ndarray 

2871 Returns the dot product of the supplied arrays. 

2872 

2873 See Also 

2874 -------- 

2875 numpy.dot : dot multiplication with two arguments. 

2876 

2877 References 

2878 ---------- 

2879 

2880 .. [1] Cormen, "Introduction to Algorithms", Chapter 15.2, p. 370-378 

2881 .. [2] https://en.wikipedia.org/wiki/Matrix_chain_multiplication 

2882 

2883 Examples 

2884 -------- 

2885 `multi_dot` allows you to write:: 

2886 

2887 >>> from numpy.linalg import multi_dot 

2888 >>> # Prepare some data 

2889 >>> A = np.random.random((10000, 100)) 

2890 >>> B = np.random.random((100, 1000)) 

2891 >>> C = np.random.random((1000, 5)) 

2892 >>> D = np.random.random((5, 333)) 

2893 >>> # the actual dot multiplication 

2894 >>> _ = multi_dot([A, B, C, D]) 

2895 

2896 instead of:: 

2897 

2898 >>> _ = np.dot(np.dot(np.dot(A, B), C), D) 

2899 >>> # or 

2900 >>> _ = A.dot(B).dot(C).dot(D) 

2901 

2902 Notes 

2903 ----- 

2904 The cost for a matrix multiplication can be calculated with the 

2905 following function:: 

2906 

2907 def cost(A, B): 

2908 return A.shape[0] * A.shape[1] * B.shape[1] 

2909 

2910 Assume we have three matrices 

2911 :math:`A_{10x100}, B_{100x5}, C_{5x50}`. 

2912 

2913 The costs for the two different parenthesizations are as follows:: 

2914 

2915 cost((AB)C) = 10*100*5 + 10*5*50 = 5000 + 2500 = 7500 

2916 cost(A(BC)) = 10*100*50 + 100*5*50 = 50000 + 25000 = 75000 

2917 

2918 """ 

2919 n = len(arrays) 

2920 # optimization only makes sense for len(arrays) > 2 

2921 if n < 2: 

2922 raise ValueError("Expecting at least two arrays.") 

2923 elif n == 2: 

2924 return dot(arrays[0], arrays[1], out=out) 

2925 

2926 arrays = [asanyarray(a) for a in arrays] 

2927 

2928 # save original ndim to reshape the result array into the proper form later 

2929 ndim_first, ndim_last = arrays[0].ndim, arrays[-1].ndim 

2930 # Explicitly convert vectors to 2D arrays to keep the logic of the internal 

2931 # _multi_dot_* functions as simple as possible. 

2932 if arrays[0].ndim == 1: 

2933 arrays[0] = atleast_2d(arrays[0]) 

2934 if arrays[-1].ndim == 1: 

2935 arrays[-1] = atleast_2d(arrays[-1]).T 

2936 _assert_2d(*arrays) 

2937 

2938 # _multi_dot_three is much faster than _multi_dot_matrix_chain_order 

2939 if n == 3: 

2940 result = _multi_dot_three(arrays[0], arrays[1], arrays[2], out=out) 

2941 else: 

2942 order = _multi_dot_matrix_chain_order(arrays) 

2943 result = _multi_dot(arrays, order, 0, n - 1, out=out) 

2944 

2945 # return proper shape 

2946 if ndim_first == 1 and ndim_last == 1: 

2947 return result[0, 0] # scalar 

2948 elif ndim_first == 1 or ndim_last == 1: 

2949 return result.ravel() # 1-D 

2950 else: 

2951 return result 

2952 

2953 

2954def _multi_dot_three(A, B, C, out=None): 

2955 """ 

2956 Find the best order for three arrays and do the multiplication. 

2957 

2958 For three arguments `_multi_dot_three` is approximately 15 times faster 

2959 than `_multi_dot_matrix_chain_order` 

2960 

2961 """ 

2962 a0, a1b0 = A.shape 

2963 b1c0, c1 = C.shape 

2964 # cost1 = cost((AB)C) = a0*a1b0*b1c0 + a0*b1c0*c1 

2965 cost1 = a0 * b1c0 * (a1b0 + c1) 

2966 # cost2 = cost(A(BC)) = a1b0*b1c0*c1 + a0*a1b0*c1 

2967 cost2 = a1b0 * c1 * (a0 + b1c0) 

2968 

2969 if cost1 < cost2: 

2970 return dot(dot(A, B), C, out=out) 

2971 else: 

2972 return dot(A, dot(B, C), out=out) 

2973 

2974 

2975def _multi_dot_matrix_chain_order(arrays, return_costs=False): 

2976 """ 

2977 Return a np.array that encodes the optimal order of mutiplications. 

2978 

2979 The optimal order array is then used by `_multi_dot()` to do the 

2980 multiplication. 

2981 

2982 Also return the cost matrix if `return_costs` is `True` 

2983 

2984 The implementation CLOSELY follows Cormen, "Introduction to Algorithms", 

2985 Chapter 15.2, p. 370-378. Note that Cormen uses 1-based indices. 

2986 

2987 cost[i, j] = min([ 

2988 cost[prefix] + cost[suffix] + cost_mult(prefix, suffix) 

2989 for k in range(i, j)]) 

2990 

2991 """ 

2992 n = len(arrays) 

2993 # p stores the dimensions of the matrices 

2994 # Example for p: A_{10x100}, B_{100x5}, C_{5x50} --> p = [10, 100, 5, 50] 

2995 p = [a.shape[0] for a in arrays] + [arrays[-1].shape[1]] 

2996 # m is a matrix of costs of the subproblems 

2997 # m[i,j]: min number of scalar multiplications needed to compute A_{i..j} 

2998 m = zeros((n, n), dtype=double) 

2999 # s is the actual ordering 

3000 # s[i, j] is the value of k at which we split the product A_i..A_j 

3001 s = empty((n, n), dtype=intp) 

3002 

3003 for l in range(1, n): 

3004 for i in range(n - l): 

3005 j = i + l 

3006 m[i, j] = inf 

3007 for k in range(i, j): 

3008 q = m[i, k] + m[k+1, j] + p[i]*p[k+1]*p[j+1] 

3009 if q < m[i, j]: 

3010 m[i, j] = q 

3011 s[i, j] = k # Note that Cormen uses 1-based index 

3012 

3013 return (s, m) if return_costs else s 

3014 

3015 

3016def _multi_dot(arrays, order, i, j, out=None): 

3017 """Actually do the multiplication with the given order.""" 

3018 if i == j: 

3019 # the initial call with non-None out should never get here 

3020 assert out is None 

3021 

3022 return arrays[i] 

3023 else: 

3024 return dot(_multi_dot(arrays, order, i, order[i, j]), 

3025 _multi_dot(arrays, order, order[i, j] + 1, j), 

3026 out=out) 

3027 

3028 

3029# diagonal 

3030 

3031def _diagonal_dispatcher(x, /, *, offset=None): 

3032 return (x,) 

3033 

3034 

3035@array_function_dispatch(_diagonal_dispatcher) 

3036def diagonal(x, /, *, offset=0): 

3037 """ 

3038 Returns specified diagonals of a matrix (or a stack of matrices) ``x``. 

3039 

3040 This function is Array API compatible, contrary to 

3041 :py:func:`numpy.diagonal`, the matrix is assumed 

3042 to be defined by the last two dimensions. 

3043 

3044 Parameters 

3045 ---------- 

3046 x : (...,M,N) array_like 

3047 Input array having shape (..., M, N) and whose innermost two 

3048 dimensions form MxN matrices. 

3049 offset : int, optional 

3050 Offset specifying the off-diagonal relative to the main diagonal, 

3051 where:: 

3052 

3053 * offset = 0: the main diagonal. 

3054 * offset > 0: off-diagonal above the main diagonal. 

3055 * offset < 0: off-diagonal below the main diagonal. 

3056 

3057 Returns 

3058 ------- 

3059 out : (...,min(N,M)) ndarray 

3060 An array containing the diagonals and whose shape is determined by 

3061 removing the last two dimensions and appending a dimension equal to 

3062 the size of the resulting diagonals. The returned array must have 

3063 the same data type as ``x``. 

3064 

3065 See Also 

3066 -------- 

3067 numpy.diagonal 

3068 

3069 """ 

3070 return _core_diagonal(x, offset, axis1=-2, axis2=-1) 

3071 

3072 

3073# trace 

3074 

3075def _trace_dispatcher(x, /, *, offset=None, dtype=None): 

3076 return (x,) 

3077 

3078 

3079@array_function_dispatch(_trace_dispatcher) 

3080def trace(x, /, *, offset=0, dtype=None): 

3081 """ 

3082 Returns the sum along the specified diagonals of a matrix 

3083 (or a stack of matrices) ``x``. 

3084 

3085 This function is Array API compatible, contrary to 

3086 :py:func:`numpy.trace`. 

3087 

3088 Parameters 

3089 ---------- 

3090 x : (...,M,N) array_like 

3091 Input array having shape (..., M, N) and whose innermost two 

3092 dimensions form MxN matrices. 

3093 offset : int, optional 

3094 Offset specifying the off-diagonal relative to the main diagonal, 

3095 where:: 

3096 

3097 * offset = 0: the main diagonal. 

3098 * offset > 0: off-diagonal above the main diagonal. 

3099 * offset < 0: off-diagonal below the main diagonal. 

3100 

3101 dtype : dtype, optional 

3102 Data type of the returned array. 

3103 

3104 Returns 

3105 ------- 

3106 out : ndarray 

3107 An array containing the traces and whose shape is determined by 

3108 removing the last two dimensions and storing the traces in the last 

3109 array dimension. For example, if x has rank k and shape: 

3110 (I, J, K, ..., L, M, N), then an output array has rank k-2 and shape: 

3111 (I, J, K, ..., L) where:: 

3112 

3113 out[i, j, k, ..., l] = trace(a[i, j, k, ..., l, :, :]) 

3114 

3115 The returned array must have a data type as described by the dtype 

3116 parameter above. 

3117 

3118 See Also 

3119 -------- 

3120 numpy.trace 

3121 

3122 """ 

3123 return _core_trace(x, offset, axis1=-2, axis2=-1, dtype=dtype) 

3124 

3125 

3126# cross 

3127 

3128def _cross_dispatcher(x1, x2, /, *, axis=None): 

3129 return (x1, x2,) 

3130 

3131 

3132@array_function_dispatch(_cross_dispatcher) 

3133def cross(x1, x2, /, *, axis=-1): 

3134 """ 

3135 Returns the cross product of 3-element vectors. 

3136 

3137 If ``x1`` and/or ``x2`` are multi-dimensional arrays, then 

3138 the cross-product of each pair of corresponding 3-element vectors 

3139 is independently computed. 

3140 

3141 This function is Array API compatible, contrary to 

3142 :func:`numpy.cross`. 

3143 

3144 Parameters 

3145 ---------- 

3146 x1 : array_like 

3147 The first input array. 

3148 x2 : array_like 

3149 The second input array. Must be compatible with ``x1`` for all 

3150 non-compute axes. The size of the axis over which to compute 

3151 the cross-product must be the same size as the respective axis 

3152 in ``x1``. 

3153 axis : int, optional 

3154 The axis (dimension) of ``x1`` and ``x2`` containing the vectors for 

3155 which to compute the cross-product. Default: ``-1``. 

3156 

3157 Returns 

3158 ------- 

3159 out : ndarray 

3160 An array containing the cross products. 

3161 

3162 See Also 

3163 -------- 

3164 numpy.cross 

3165 

3166 """ 

3167 if x1.shape[axis] != 3 or x2.shape[axis] != 3: 

3168 raise ValueError( 

3169 "Both input arrays must be (arrays of) 3-dimensional vectors, " 

3170 f"but they are {x1.shape[axis]} and {x2.shape[axis]} " 

3171 "dimensional instead." 

3172 ) 

3173 

3174 return _core_cross(x1, x2, axis=axis) 

3175 

3176 

3177# matmul 

3178 

3179def _matmul_dispatcher(x1, x2, /): 

3180 return (x1, x2) 

3181 

3182 

3183@array_function_dispatch(_matmul_dispatcher) 

3184def matmul(x1, x2, /): 

3185 """ 

3186 Computes the matrix product. 

3187 

3188 This function is Array API compatible, contrary to 

3189 :func:`numpy.matmul`. 

3190 

3191 Parameters 

3192 ---------- 

3193 x1 : array_like 

3194 The first input array. 

3195 x2 : array_like 

3196 The second input array. 

3197 

3198 Returns 

3199 ------- 

3200 out : ndarray 

3201 The matrix product of the inputs. 

3202 This is a scalar only when both ``x1``, ``x2`` are 1-d vectors. 

3203 

3204 Raises 

3205 ------ 

3206 ValueError 

3207 If the last dimension of ``x1`` is not the same size as 

3208 the second-to-last dimension of ``x2``. 

3209 

3210 If a scalar value is passed in. 

3211 

3212 See Also 

3213 -------- 

3214 numpy.matmul 

3215 

3216 """ 

3217 return _core_matmul(x1, x2) 

3218 

3219 

3220# tensordot 

3221 

3222def _tensordot_dispatcher(x1, x2, /, *, axes=None): 

3223 return (x1, x2) 

3224 

3225 

3226@array_function_dispatch(_tensordot_dispatcher) 

3227def tensordot(x1, x2, /, *, axes=2): 

3228 return _core_tensordot(x1, x2, axes=axes) 

3229 

3230 

3231tensordot.__doc__ = _core_tensordot.__doc__ 

3232 

3233 

3234# matrix_transpose 

3235 

3236def _matrix_transpose_dispatcher(x): 

3237 return (x,) 

3238 

3239@array_function_dispatch(_matrix_transpose_dispatcher) 

3240def matrix_transpose(x, /): 

3241 return _core_matrix_transpose(x) 

3242 

3243 

3244matrix_transpose.__doc__ = _core_matrix_transpose.__doc__ 

3245 

3246 

3247# matrix_norm 

3248 

3249def _matrix_norm_dispatcher(x, /, *, keepdims=None, ord=None): 

3250 return (x,) 

3251 

3252@array_function_dispatch(_matrix_norm_dispatcher) 

3253def matrix_norm(x, /, *, keepdims=False, ord="fro"): 

3254 """ 

3255 Computes the matrix norm of a matrix (or a stack of matrices) ``x``. 

3256 

3257 This function is Array API compatible. 

3258 

3259 Parameters 

3260 ---------- 

3261 x : array_like 

3262 Input array having shape (..., M, N) and whose two innermost 

3263 dimensions form ``MxN`` matrices. 

3264 keepdims : bool, optional 

3265 If this is set to True, the axes which are normed over are left in 

3266 the result as dimensions with size one. Default: False. 

3267 ord : {1, -1, 2, -2, inf, -inf, 'fro', 'nuc'}, optional 

3268 The order of the norm. For details see the table under ``Notes`` 

3269 in `numpy.linalg.norm`. 

3270 

3271 See Also 

3272 -------- 

3273 numpy.linalg.norm : Generic norm function 

3274 

3275 """ 

3276 x = asanyarray(x) 

3277 return norm(x, axis=(-2, -1), keepdims=keepdims, ord=ord) 

3278 

3279 

3280# vector_norm 

3281 

3282def _vector_norm_dispatcher(x, /, *, axis=None, keepdims=None, ord=None): 

3283 return (x,) 

3284 

3285@array_function_dispatch(_vector_norm_dispatcher) 

3286def vector_norm(x, /, *, axis=None, keepdims=False, ord=2): 

3287 """ 

3288 Computes the vector norm of a vector (or batch of vectors) ``x``. 

3289 

3290 This function is Array API compatible. 

3291 

3292 Parameters 

3293 ---------- 

3294 x : array_like 

3295 Input array. 

3296 axis : {None, int, 2-tuple of ints}, optional 

3297 If an integer, ``axis`` specifies the axis (dimension) along which 

3298 to compute vector norms. If an n-tuple, ``axis`` specifies the axes 

3299 (dimensions) along which to compute batched vector norms. If ``None``, 

3300 the vector norm must be computed over all array values (i.e., 

3301 equivalent to computing the vector norm of a flattened array). 

3302 Default: ``None``. 

3303 keepdims : bool, optional 

3304 If this is set to True, the axes which are normed over are left in 

3305 the result as dimensions with size one. Default: False. 

3306 ord : {1, -1, 2, -2, inf, -inf, 'fro', 'nuc'}, optional 

3307 The order of the norm. For details see the table under ``Notes`` 

3308 in `numpy.linalg.norm`. 

3309 

3310 See Also 

3311 -------- 

3312 numpy.linalg.norm : Generic norm function 

3313 

3314 """ 

3315 x = asanyarray(x) 

3316 shape = list(x.shape) 

3317 if axis is None: 

3318 # Note: np.linalg.norm() doesn't handle 0-D arrays 

3319 x = x.ravel() 

3320 _axis = 0 

3321 elif isinstance(axis, tuple): 

3322 # Note: The axis argument supports any number of axes, whereas 

3323 # np.linalg.norm() only supports a single axis for vector norm. 

3324 normalized_axis = normalize_axis_tuple(axis, x.ndim) 

3325 rest = tuple(i for i in range(x.ndim) if i not in normalized_axis) 

3326 newshape = axis + rest 

3327 x = _core_transpose(x, newshape).reshape( 

3328 ( 

3329 prod([x.shape[i] for i in axis], dtype=int), 

3330 *[x.shape[i] for i in rest] 

3331 ) 

3332 ) 

3333 _axis = 0 

3334 else: 

3335 _axis = axis 

3336 

3337 res = norm(x, axis=_axis, ord=ord) 

3338 

3339 if keepdims: 

3340 # We can't reuse np.linalg.norm(keepdims) because of the reshape hacks 

3341 # above to avoid matrix norm logic. 

3342 _axis = normalize_axis_tuple( 

3343 range(len(shape)) if axis is None else axis, len(shape) 

3344 ) 

3345 for i in _axis: 

3346 shape[i] = 1 

3347 res = res.reshape(tuple(shape)) 

3348 

3349 return res 

3350 

3351 

3352# vecdot 

3353 

3354def _vecdot_dispatcher(x1, x2, /, *, axis=None): 

3355 return (x1, x2) 

3356 

3357@array_function_dispatch(_vecdot_dispatcher) 

3358def vecdot(x1, x2, /, *, axis=-1): 

3359 """ 

3360 Computes the vector dot product. 

3361 

3362 This function is restricted to arguments compatible with the Array API, 

3363 contrary to :func:`numpy.vecdot`. 

3364 

3365 Let :math:`\\mathbf{a}` be a vector in ``x1`` and :math:`\\mathbf{b}` be 

3366 a corresponding vector in ``x2``. The dot product is defined as: 

3367 

3368 .. math:: 

3369 \\mathbf{a} \\cdot \\mathbf{b} = \\sum_{i=0}^{n-1} \\overline{a_i}b_i 

3370 

3371 over the dimension specified by ``axis`` and where :math:`\\overline{a_i}` 

3372 denotes the complex conjugate if :math:`a_i` is complex and the identity 

3373 otherwise. 

3374 

3375 Parameters 

3376 ---------- 

3377 x1 : array_like 

3378 First input array. 

3379 x2 : array_like 

3380 Second input array. 

3381 axis : int, optional 

3382 Axis over which to compute the dot product. Default: ``-1``. 

3383 

3384 Returns 

3385 ------- 

3386 output : ndarray 

3387 The vector dot product of the input. 

3388 

3389 See Also 

3390 -------- 

3391 numpy.vecdot 

3392 

3393 """ 

3394 return _core_vecdot(x1, x2, axis=axis)