def qrp(A, rank = None, extra_prec = 16): m = A.nrows() n = A.ncols() s = min(m,n) if rank is not None: #s = min(s, rank + 1); pass; base_prec = A.base_ring().precision(); base_field = A.base_ring() if is_ComplexField(base_field): field = ComplexField(base_prec + extra_prec + m); else: field = RealField(base_prec + extra_prec + m); # field = base_field; R = copy(A); A = A.change_ring(field); P = [ j for j in xrange(n) ]; Q = identity_matrix(field,m) # print A.base_ring() # print Q.base_ring() normbound = field(2)**(-0.5*field.precision()); colnorms2 = [ float_sum([ R[k,j].norm() for k in range(m)]) for j in range(n) ]; for j in xrange(s): # find column with max norm maxnorm2 = colnorms2[j]; p = j; for k in xrange(j, n): if colnorms2[k] > maxnorm2: p = k; maxnorm2 = colnorms2[k]; #it is worth it to recompute the maxnorm xnorm2 = float_sum([ R[i,p].norm() for i in range(j, m)]) xnorm = sqrt(xnorm2); # swap j and p in A, P and colnorms if j != p: P[j], P[p] = P[p], P[j] colnorms2[j], colnorms2[p] = colnorms2[p], colnorms2[j] for i in xrange(0, m): R[i, j], R[i, p] = R[i, p], R[i, j]; # compute householder vector u = [ R[k,j] for k in xrange(j, m) ]; alpha = R[j,j]; # alphanorm = alpha.abs(); if alpha.real() < 0: u[0] -= xnorm z = -1 else: u[0] += xnorm z = 1 beta = xnorm*(xnorm + alpha * z); if beta.abs() < normbound: beta = float_sum( [u[i].conjugate() * R[i+j,j] for i in range(m - j)]) if beta == field(0): break; beta = 1/beta; # H = I - beta * u * u^* # Apply householder matrix #update R R[j,j] = -z * xnorm; for i in xrange(j+1,m): R[i,j] = 0 for k in xrange(j+1, n): lambdR = beta * float_sum( [u[l - j].conjugate() * R[l, k] for l in xrange(j, m)] ); for i in xrange(j, m): R[i, k] -= lambdR * u[i - j]; #update Q for k in xrange(m): lambdQ = float_sum( [u[l - j].conjugate() * Q[l, k] for l in xrange(j, m)] ); lambdQ *= beta for i in xrange(j,m): Q[i, k] -= lambdQ * u[i - j]; for k in xrange(j + 1, n): square = R[j,k].norm(); colnorms2[k] -= square; # sometimes is better to just recompute the norm if True: #colnorms2[k] < normbound or colnorms2[k] < square*normbound: colnorms2[k] = float_sum([ R[i,k].norm() for i in range(j + 1, m)]) # compute P matrix Pmatrix = Matrix(ZZ, n); for i in xrange(n): Pmatrix[ P[i], i] = 1; return Q.conjugate_transpose().change_ring(base_field), R.change_ring(base_field), Pmatrix;