| """ |
| Linear algebra |
| -------------- |
| |
| Linear equations |
| ................ |
| |
| Basic linear algebra is implemented; you can for example solve the linear |
| equation system:: |
| |
| x + 2*y = -10 |
| 3*x + 4*y = 10 |
| |
| using ``lu_solve``:: |
| |
| >>> from mpmath import * |
| >>> mp.pretty = False |
| >>> A = matrix([[1, 2], [3, 4]]) |
| >>> b = matrix([-10, 10]) |
| >>> x = lu_solve(A, b) |
| >>> x |
| matrix( |
| [['30.0'], |
| ['-20.0']]) |
| |
| If you don't trust the result, use ``residual`` to calculate the residual ||A*x-b||:: |
| |
| >>> residual(A, x, b) |
| matrix( |
| [['3.46944695195361e-18'], |
| ['3.46944695195361e-18']]) |
| >>> str(eps) |
| '2.22044604925031e-16' |
| |
| As you can see, the solution is quite accurate. The error is caused by the |
| inaccuracy of the internal floating point arithmetic. Though, it's even smaller |
| than the current machine epsilon, which basically means you can trust the |
| result. |
| |
| If you need more speed, use NumPy, or ``fp.lu_solve`` for a floating-point computation. |
| |
| >>> fp.lu_solve(A, b) # doctest: +ELLIPSIS |
| matrix(...) |
| |
| ``lu_solve`` accepts overdetermined systems. It is usually not possible to solve |
| such systems, so the residual is minimized instead. Internally this is done |
| using Cholesky decomposition to compute a least squares approximation. This means |
| that that ``lu_solve`` will square the errors. If you can't afford this, use |
| ``qr_solve`` instead. It is twice as slow but more accurate, and it calculates |
| the residual automatically. |
| |
| |
| Matrix factorization |
| .................... |
| |
| The function ``lu`` computes an explicit LU factorization of a matrix:: |
| |
| >>> P, L, U = lu(matrix([[0,2,3],[4,5,6],[7,8,9]])) |
| >>> print(P) |
| [0.0 0.0 1.0] |
| [1.0 0.0 0.0] |
| [0.0 1.0 0.0] |
| >>> print(L) |
| [ 1.0 0.0 0.0] |
| [ 0.0 1.0 0.0] |
| [0.571428571428571 0.214285714285714 1.0] |
| >>> print(U) |
| [7.0 8.0 9.0] |
| [0.0 2.0 3.0] |
| [0.0 0.0 0.214285714285714] |
| >>> print(P.T*L*U) |
| [0.0 2.0 3.0] |
| [4.0 5.0 6.0] |
| [7.0 8.0 9.0] |
| |
| Interval matrices |
| ----------------- |
| |
| Matrices may contain interval elements. This allows one to perform |
| basic linear algebra operations such as matrix multiplication |
| and equation solving with rigorous error bounds:: |
| |
| >>> a = iv.matrix([['0.1','0.3','1.0'], |
| ... ['7.1','5.5','4.8'], |
| ... ['3.2','4.4','5.6']]) |
| >>> |
| >>> b = iv.matrix(['4','0.6','0.5']) |
| >>> c = iv.lu_solve(a, b) |
| >>> print(c) |
| [ [5.2582327113062568605927528666, 5.25823271130625686059275702219]] |
| [[-13.1550493962678375411635581388, -13.1550493962678375411635540152]] |
| [ [7.42069154774972557628979076189, 7.42069154774972557628979190734]] |
| >>> print(a*c) |
| [ [3.99999999999999999999999844904, 4.00000000000000000000000155096]] |
| [[0.599999999999999999999968898009, 0.600000000000000000000031763736]] |
| [[0.499999999999999999999979320485, 0.500000000000000000000020679515]] |
| """ |
|
|
| |
| |
| |
| |
|
|
| from copy import copy |
|
|
| from ..libmp.backend import xrange |
|
|
| class LinearAlgebraMethods(object): |
|
|
| def LU_decomp(ctx, A, overwrite=False, use_cache=True): |
| """ |
| LU-factorization of a n*n matrix using the Gauss algorithm. |
| Returns L and U in one matrix and the pivot indices. |
| |
| Use overwrite to specify whether A will be overwritten with L and U. |
| """ |
| if not A.rows == A.cols: |
| raise ValueError('need n*n matrix') |
| |
| if use_cache and isinstance(A, ctx.matrix) and A._LU: |
| return A._LU |
| if not overwrite: |
| orig = A |
| A = A.copy() |
| tol = ctx.absmin(ctx.mnorm(A,1) * ctx.eps) |
| n = A.rows |
| p = [None]*(n - 1) |
| for j in xrange(n - 1): |
| |
| biggest = 0 |
| for k in xrange(j, n): |
| s = ctx.fsum([ctx.absmin(A[k,l]) for l in xrange(j, n)]) |
| if ctx.absmin(s) <= tol: |
| raise ZeroDivisionError('matrix is numerically singular') |
| current = 1/s * ctx.absmin(A[k,j]) |
| if current > biggest: |
| biggest = current |
| p[j] = k |
| |
| ctx.swap_row(A, j, p[j]) |
| if ctx.absmin(A[j,j]) <= tol: |
| raise ZeroDivisionError('matrix is numerically singular') |
| |
| for i in xrange(j + 1, n): |
| A[i,j] /= A[j,j] |
| for k in xrange(j + 1, n): |
| A[i,k] -= A[i,j]*A[j,k] |
| if ctx.absmin(A[n - 1,n - 1]) <= tol: |
| raise ZeroDivisionError('matrix is numerically singular') |
| |
| if not overwrite and isinstance(orig, ctx.matrix): |
| orig._LU = (A, p) |
| return A, p |
|
|
| def L_solve(ctx, L, b, p=None): |
| """ |
| Solve the lower part of a LU factorized matrix for y. |
| """ |
| if L.rows != L.cols: |
| raise RuntimeError("need n*n matrix") |
| n = L.rows |
| if len(b) != n: |
| raise ValueError("Value should be equal to n") |
| b = copy(b) |
| if p: |
| for k in xrange(0, len(p)): |
| ctx.swap_row(b, k, p[k]) |
| |
| for i in xrange(1, n): |
| for j in xrange(i): |
| b[i] -= L[i,j] * b[j] |
| return b |
|
|
| def U_solve(ctx, U, y): |
| """ |
| Solve the upper part of a LU factorized matrix for x. |
| """ |
| if U.rows != U.cols: |
| raise RuntimeError("need n*n matrix") |
| n = U.rows |
| if len(y) != n: |
| raise ValueError("Value should be equal to n") |
| x = copy(y) |
| for i in xrange(n - 1, -1, -1): |
| for j in xrange(i + 1, n): |
| x[i] -= U[i,j] * x[j] |
| x[i] /= U[i,i] |
| return x |
|
|
| def lu_solve(ctx, A, b, **kwargs): |
| """ |
| Ax = b => x |
| |
| Solve a determined or overdetermined linear equations system. |
| Fast LU decomposition is used, which is less accurate than QR decomposition |
| (especially for overdetermined systems), but it's twice as efficient. |
| Use qr_solve if you want more precision or have to solve a very ill- |
| conditioned system. |
| |
| If you specify real=True, it does not check for overdeterminded complex |
| systems. |
| """ |
| prec = ctx.prec |
| try: |
| ctx.prec += 10 |
| |
| A, b = ctx.matrix(A, **kwargs).copy(), ctx.matrix(b, **kwargs).copy() |
| if A.rows < A.cols: |
| raise ValueError('cannot solve underdetermined system') |
| if A.rows > A.cols: |
| |
| |
| AH = A.H |
| A = AH * A |
| b = AH * b |
| if (kwargs.get('real', False) or |
| not sum(type(i) is ctx.mpc for i in A)): |
| |
| x = ctx.cholesky_solve(A, b) |
| else: |
| x = ctx.lu_solve(A, b) |
| else: |
| |
| A, p = ctx.LU_decomp(A) |
| b = ctx.L_solve(A, b, p) |
| x = ctx.U_solve(A, b) |
| finally: |
| ctx.prec = prec |
| return x |
|
|
| def improve_solution(ctx, A, x, b, maxsteps=1): |
| """ |
| Improve a solution to a linear equation system iteratively. |
| |
| This re-uses the LU decomposition and is thus cheap. |
| Usually 3 up to 4 iterations are giving the maximal improvement. |
| """ |
| if A.rows != A.cols: |
| raise RuntimeError("need n*n matrix") |
| for _ in xrange(maxsteps): |
| r = ctx.residual(A, x, b) |
| if ctx.norm(r, 2) < 10*ctx.eps: |
| break |
| |
| dx = ctx.lu_solve(A, -r) |
| x += dx |
| return x |
|
|
| def lu(ctx, A): |
| """ |
| A -> P, L, U |
| |
| LU factorisation of a square matrix A. L is the lower, U the upper part. |
| P is the permutation matrix indicating the row swaps. |
| |
| P*A = L*U |
| |
| If you need efficiency, use the low-level method LU_decomp instead, it's |
| much more memory efficient. |
| """ |
| |
| A, p = ctx.LU_decomp(A) |
| n = A.rows |
| L = ctx.matrix(n) |
| U = ctx.matrix(n) |
| for i in xrange(n): |
| for j in xrange(n): |
| if i > j: |
| L[i,j] = A[i,j] |
| elif i == j: |
| L[i,j] = 1 |
| U[i,j] = A[i,j] |
| else: |
| U[i,j] = A[i,j] |
| |
| P = ctx.eye(n) |
| for k in xrange(len(p)): |
| ctx.swap_row(P, k, p[k]) |
| return P, L, U |
|
|
| def unitvector(ctx, n, i): |
| """ |
| Return the i-th n-dimensional unit vector. |
| """ |
| assert 0 < i <= n, 'this unit vector does not exist' |
| return [ctx.zero]*(i-1) + [ctx.one] + [ctx.zero]*(n-i) |
|
|
| def inverse(ctx, A, **kwargs): |
| """ |
| Calculate the inverse of a matrix. |
| |
| If you want to solve an equation system Ax = b, it's recommended to use |
| solve(A, b) instead, it's about 3 times more efficient. |
| """ |
| prec = ctx.prec |
| try: |
| ctx.prec += 10 |
| |
| A = ctx.matrix(A, **kwargs).copy() |
| n = A.rows |
| |
| A, p = ctx.LU_decomp(A) |
| cols = [] |
| |
| for i in xrange(1, n + 1): |
| e = ctx.unitvector(n, i) |
| y = ctx.L_solve(A, e, p) |
| cols.append(ctx.U_solve(A, y)) |
| |
| inv = [] |
| for i in xrange(n): |
| row = [] |
| for j in xrange(n): |
| row.append(cols[j][i]) |
| inv.append(row) |
| result = ctx.matrix(inv, **kwargs) |
| finally: |
| ctx.prec = prec |
| return result |
|
|
| def householder(ctx, A): |
| """ |
| (A|b) -> H, p, x, res |
| |
| (A|b) is the coefficient matrix with left hand side of an optionally |
| overdetermined linear equation system. |
| H and p contain all information about the transformation matrices. |
| x is the solution, res the residual. |
| """ |
| if not isinstance(A, ctx.matrix): |
| raise TypeError("A should be a type of ctx.matrix") |
| m = A.rows |
| n = A.cols |
| if m < n - 1: |
| raise RuntimeError("Columns should not be less than rows") |
| |
| p = [] |
| for j in xrange(0, n - 1): |
| s = ctx.fsum(abs(A[i,j])**2 for i in xrange(j, m)) |
| if not abs(s) > ctx.eps: |
| raise ValueError('matrix is numerically singular') |
| p.append(-ctx.sign(ctx.re(A[j,j])) * ctx.sqrt(s)) |
| kappa = ctx.one / (s - p[j] * A[j,j]) |
| A[j,j] -= p[j] |
| for k in xrange(j+1, n): |
| y = ctx.fsum(ctx.conj(A[i,j]) * A[i,k] for i in xrange(j, m)) * kappa |
| for i in xrange(j, m): |
| A[i,k] -= A[i,j] * y |
| |
| x = [A[i,n - 1] for i in xrange(n - 1)] |
| for i in xrange(n - 2, -1, -1): |
| x[i] -= ctx.fsum(A[i,j] * x[j] for j in xrange(i + 1, n - 1)) |
| x[i] /= p[i] |
| |
| if not m == n - 1: |
| r = [A[m-1-i, n-1] for i in xrange(m - n + 1)] |
| else: |
| |
| r = [0]*m |
| return A, p, x, r |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| def residual(ctx, A, x, b, **kwargs): |
| """ |
| Calculate the residual of a solution to a linear equation system. |
| |
| r = A*x - b for A*x = b |
| """ |
| oldprec = ctx.prec |
| try: |
| ctx.prec *= 2 |
| A, x, b = ctx.matrix(A, **kwargs), ctx.matrix(x, **kwargs), ctx.matrix(b, **kwargs) |
| return A*x - b |
| finally: |
| ctx.prec = oldprec |
|
|
| def qr_solve(ctx, A, b, norm=None, **kwargs): |
| """ |
| Ax = b => x, ||Ax - b|| |
| |
| Solve a determined or overdetermined linear equations system and |
| calculate the norm of the residual (error). |
| QR decomposition using Householder factorization is applied, which gives very |
| accurate results even for ill-conditioned matrices. qr_solve is twice as |
| efficient. |
| """ |
| if norm is None: |
| norm = ctx.norm |
| prec = ctx.prec |
| try: |
| ctx.prec += 10 |
| |
| A, b = ctx.matrix(A, **kwargs).copy(), ctx.matrix(b, **kwargs).copy() |
| if A.rows < A.cols: |
| raise ValueError('cannot solve underdetermined system') |
| H, p, x, r = ctx.householder(ctx.extend(A, b)) |
| res = ctx.norm(r) |
| |
| if res == 0: |
| res = ctx.norm(ctx.residual(A, x, b)) |
| return ctx.matrix(x, **kwargs), res |
| finally: |
| ctx.prec = prec |
|
|
| def cholesky(ctx, A, tol=None): |
| r""" |
| Cholesky decomposition of a symmetric positive-definite matrix `A`. |
| Returns a lower triangular matrix `L` such that `A = L \times L^T`. |
| More generally, for a complex Hermitian positive-definite matrix, |
| a Cholesky decomposition satisfying `A = L \times L^H` is returned. |
| |
| The Cholesky decomposition can be used to solve linear equation |
| systems twice as efficiently as LU decomposition, or to |
| test whether `A` is positive-definite. |
| |
| The optional parameter ``tol`` determines the tolerance for |
| verifying positive-definiteness. |
| |
| **Examples** |
| |
| Cholesky decomposition of a positive-definite symmetric matrix:: |
| |
| >>> from mpmath import * |
| >>> mp.dps = 25; mp.pretty = True |
| >>> A = eye(3) + hilbert(3) |
| >>> nprint(A) |
| [ 2.0 0.5 0.333333] |
| [ 0.5 1.33333 0.25] |
| [0.333333 0.25 1.2] |
| >>> L = cholesky(A) |
| >>> nprint(L) |
| [ 1.41421 0.0 0.0] |
| [0.353553 1.09924 0.0] |
| [0.235702 0.15162 1.05899] |
| >>> chop(A - L*L.T) |
| [0.0 0.0 0.0] |
| [0.0 0.0 0.0] |
| [0.0 0.0 0.0] |
| |
| Cholesky decomposition of a Hermitian matrix:: |
| |
| >>> A = eye(3) + matrix([[0,0.25j,-0.5j],[-0.25j,0,0],[0.5j,0,0]]) |
| >>> L = cholesky(A) |
| >>> nprint(L) |
| [ 1.0 0.0 0.0] |
| [(0.0 - 0.25j) (0.968246 + 0.0j) 0.0] |
| [ (0.0 + 0.5j) (0.129099 + 0.0j) (0.856349 + 0.0j)] |
| >>> chop(A - L*L.H) |
| [0.0 0.0 0.0] |
| [0.0 0.0 0.0] |
| [0.0 0.0 0.0] |
| |
| Attempted Cholesky decomposition of a matrix that is not positive |
| definite:: |
| |
| >>> A = -eye(3) + hilbert(3) |
| >>> L = cholesky(A) |
| Traceback (most recent call last): |
| ... |
| ValueError: matrix is not positive-definite |
| |
| **References** |
| |
| 1. [Wikipedia]_ http://en.wikipedia.org/wiki/Cholesky_decomposition |
| |
| """ |
| if not isinstance(A, ctx.matrix): |
| raise RuntimeError("A should be a type of ctx.matrix") |
| if not A.rows == A.cols: |
| raise ValueError('need n*n matrix') |
| if tol is None: |
| tol = +ctx.eps |
| n = A.rows |
| L = ctx.matrix(n) |
| for j in xrange(n): |
| c = ctx.re(A[j,j]) |
| if abs(c-A[j,j]) > tol: |
| raise ValueError('matrix is not Hermitian') |
| s = c - ctx.fsum((L[j,k] for k in xrange(j)), |
| absolute=True, squared=True) |
| if s < tol: |
| raise ValueError('matrix is not positive-definite') |
| L[j,j] = ctx.sqrt(s) |
| for i in xrange(j, n): |
| it1 = (L[i,k] for k in xrange(j)) |
| it2 = (L[j,k] for k in xrange(j)) |
| t = ctx.fdot(it1, it2, conjugate=True) |
| L[i,j] = (A[i,j] - t) / L[j,j] |
| return L |
|
|
| def cholesky_solve(ctx, A, b, **kwargs): |
| """ |
| Ax = b => x |
| |
| Solve a symmetric positive-definite linear equation system. |
| This is twice as efficient as lu_solve. |
| |
| Typical use cases: |
| * A.T*A |
| * Hessian matrix |
| * differential equations |
| """ |
| prec = ctx.prec |
| try: |
| ctx.prec += 10 |
| |
| A, b = ctx.matrix(A, **kwargs).copy(), ctx.matrix(b, **kwargs).copy() |
| if A.rows != A.cols: |
| raise ValueError('can only solve determined system') |
| |
| L = ctx.cholesky(A) |
| |
| n = L.rows |
| if len(b) != n: |
| raise ValueError("Value should be equal to n") |
| for i in xrange(n): |
| b[i] -= ctx.fsum(L[i,j] * b[j] for j in xrange(i)) |
| b[i] /= L[i,i] |
| x = ctx.U_solve(L.T, b) |
| return x |
| finally: |
| ctx.prec = prec |
|
|
| def det(ctx, A): |
| """ |
| Calculate the determinant of a matrix. |
| """ |
| prec = ctx.prec |
| try: |
| |
| A = ctx.matrix(A).copy() |
| |
| try: |
| R, p = ctx.LU_decomp(A) |
| except ZeroDivisionError: |
| return 0 |
| z = 1 |
| for i, e in enumerate(p): |
| if i != e: |
| z *= -1 |
| for i in xrange(A.rows): |
| z *= R[i,i] |
| return z |
| finally: |
| ctx.prec = prec |
|
|
| def cond(ctx, A, norm=None): |
| """ |
| Calculate the condition number of a matrix using a specified matrix norm. |
| |
| The condition number estimates the sensitivity of a matrix to errors. |
| Example: small input errors for ill-conditioned coefficient matrices |
| alter the solution of the system dramatically. |
| |
| For ill-conditioned matrices it's recommended to use qr_solve() instead |
| of lu_solve(). This does not help with input errors however, it just avoids |
| to add additional errors. |
| |
| Definition: cond(A) = ||A|| * ||A**-1|| |
| """ |
| if norm is None: |
| norm = lambda x: ctx.mnorm(x,1) |
| return norm(A) * norm(ctx.inverse(A)) |
|
|
| def lu_solve_mat(ctx, a, b): |
| """Solve a * x = b where a and b are matrices.""" |
| r = ctx.matrix(a.rows, b.cols) |
| for i in range(b.cols): |
| c = ctx.lu_solve(a, b.column(i)) |
| for j in range(len(c)): |
| r[j, i] = c[j] |
| return r |
|
|
| def qr(ctx, A, mode = 'full', edps = 10): |
| """ |
| Compute a QR factorization $A = QR$ where |
| A is an m x n matrix of real or complex numbers where m >= n |
| |
| mode has following meanings: |
| (1) mode = 'raw' returns two matrixes (A, tau) in the |
| internal format used by LAPACK |
| (2) mode = 'skinny' returns the leading n columns of Q |
| and n rows of R |
| (3) Any other value returns the leading m columns of Q |
| and m rows of R |
| |
| edps is the increase in mp precision used for calculations |
| |
| **Examples** |
| |
| >>> from mpmath import * |
| >>> mp.dps = 15 |
| >>> mp.pretty = True |
| >>> A = matrix([[1, 2], [3, 4], [1, 1]]) |
| >>> Q, R = qr(A) |
| >>> Q |
| [-0.301511344577764 0.861640436855329 0.408248290463863] |
| [-0.904534033733291 -0.123091490979333 -0.408248290463863] |
| [-0.301511344577764 -0.492365963917331 0.816496580927726] |
| >>> R |
| [-3.3166247903554 -4.52267016866645] |
| [ 0.0 0.738548945875996] |
| [ 0.0 0.0] |
| >>> Q * R |
| [1.0 2.0] |
| [3.0 4.0] |
| [1.0 1.0] |
| >>> chop(Q.T * Q) |
| [1.0 0.0 0.0] |
| [0.0 1.0 0.0] |
| [0.0 0.0 1.0] |
| >>> B = matrix([[1+0j, 2-3j], [3+j, 4+5j]]) |
| >>> Q, R = qr(B) |
| >>> nprint(Q) |
| [ (-0.301511 + 0.0j) (0.0695795 - 0.95092j)] |
| [(-0.904534 - 0.301511j) (-0.115966 + 0.278318j)] |
| >>> nprint(R) |
| [(-3.31662 + 0.0j) (-5.72872 - 2.41209j)] |
| [ 0.0 (3.91965 + 0.0j)] |
| >>> Q * R |
| [(1.0 + 0.0j) (2.0 - 3.0j)] |
| [(3.0 + 1.0j) (4.0 + 5.0j)] |
| >>> chop(Q.T * Q.conjugate()) |
| [1.0 0.0] |
| [0.0 1.0] |
| |
| """ |
|
|
| |
| assert isinstance(A, ctx.matrix) |
| m = A.rows |
| n = A.cols |
| assert n >= 0 |
| assert m >= n |
| assert edps >= 0 |
|
|
| |
| cmplx = any(type(x) is ctx.mpc for x in A) |
|
|
| |
| with ctx.extradps(edps): |
| tau = ctx.matrix(n,1) |
| A = A.copy() |
|
|
| |
| |
| |
| if cmplx: |
| one = ctx.mpc('1.0', '0.0') |
| zero = ctx.mpc('0.0', '0.0') |
| rzero = ctx.mpf('0.0') |
|
|
| |
| for j in xrange(0, n): |
| alpha = A[j,j] |
| alphr = ctx.re(alpha) |
| alphi = ctx.im(alpha) |
|
|
| if (m-j) >= 2: |
| xnorm = ctx.fsum( A[i,j]*ctx.conj(A[i,j]) for i in xrange(j+1, m) ) |
| xnorm = ctx.re( ctx.sqrt(xnorm) ) |
| else: |
| xnorm = rzero |
|
|
| if (xnorm == rzero) and (alphi == rzero): |
| tau[j] = zero |
| continue |
|
|
| if alphr < rzero: |
| beta = ctx.sqrt(alphr**2 + alphi**2 + xnorm**2) |
| else: |
| beta = -ctx.sqrt(alphr**2 + alphi**2 + xnorm**2) |
|
|
| tau[j] = ctx.mpc( (beta - alphr) / beta, -alphi / beta ) |
| t = -ctx.conj(tau[j]) |
| za = one / (alpha - beta) |
|
|
| for i in xrange(j+1, m): |
| A[i,j] *= za |
|
|
| A[j,j] = one |
| for k in xrange(j+1, n): |
| y = ctx.fsum(A[i,j] * ctx.conj(A[i,k]) for i in xrange(j, m)) |
| temp = t * ctx.conj(y) |
| for i in xrange(j, m): |
| A[i,k] += A[i,j] * temp |
|
|
| A[j,j] = ctx.mpc(beta, '0.0') |
| else: |
| one = ctx.mpf('1.0') |
| zero = ctx.mpf('0.0') |
|
|
| |
| for j in xrange(0, n): |
| alpha = A[j,j] |
|
|
| if (m-j) > 2: |
| xnorm = ctx.fsum( (A[i,j])**2 for i in xrange(j+1, m) ) |
| xnorm = ctx.sqrt(xnorm) |
| elif (m-j) == 2: |
| xnorm = abs( A[m-1,j] ) |
| else: |
| xnorm = zero |
|
|
| if xnorm == zero: |
| tau[j] = zero |
| continue |
|
|
| if alpha < zero: |
| beta = ctx.sqrt(alpha**2 + xnorm**2) |
| else: |
| beta = -ctx.sqrt(alpha**2 + xnorm**2) |
|
|
| tau[j] = (beta - alpha) / beta |
| t = -tau[j] |
| da = one / (alpha - beta) |
|
|
| for i in xrange(j+1, m): |
| A[i,j] *= da |
|
|
| A[j,j] = one |
| for k in xrange(j+1, n): |
| y = ctx.fsum( A[i,j] * A[i,k] for i in xrange(j, m) ) |
| temp = t * y |
| for i in xrange(j,m): |
| A[i,k] += A[i,j] * temp |
|
|
| A[j,j] = beta |
|
|
| |
| if (mode == 'raw') or (mode == 'RAW'): |
| return A, tau |
|
|
| |
| |
| |
|
|
| |
| R = A.copy() |
| for j in xrange(0, n): |
| for i in xrange(j+1, m): |
| R[i,j] = zero |
|
|
| |
| p = m |
| if (mode == 'skinny') or (mode == 'SKINNY'): |
| p = n |
|
|
| |
| A.cols += (p-n) |
| for j in xrange(0, p): |
| A[j,j] = one |
| for i in xrange(0, j): |
| A[i,j] = zero |
|
|
| |
| for j in xrange(n-1, -1, -1): |
| t = -tau[j] |
| A[j,j] += t |
|
|
| for k in xrange(j+1, p): |
| if cmplx: |
| y = ctx.fsum(A[i,j] * ctx.conj(A[i,k]) for i in xrange(j+1, m)) |
| temp = t * ctx.conj(y) |
| else: |
| y = ctx.fsum(A[i,j] * A[i,k] for i in xrange(j+1, m)) |
| temp = t * y |
| A[j,k] = temp |
| for i in xrange(j+1, m): |
| A[i,k] += A[i,j] * temp |
|
|
| for i in xrange(j+1, m): |
| A[i, j] *= t |
|
|
| return A, R[0:p,0:n] |
|
|
| |
| |
| |
|
|