#include "cminpack.h" #include #ifdef USE_LAPACK #include #include #include #endif #include "cminpackP.h" __cminpack_attr__ void __cminpack_func__(qrfac)(int m, int n, real *a, int lda, int pivot, int *ipvt, int lipvt, real *rdiag, real *acnorm, real *wa) { #ifdef USE_LAPACK __CLPK_integer m_ = m; __CLPK_integer n_ = n; __CLPK_integer lda_ = lda; __CLPK_integer *jpvt; int i, j, k; double t; double* tau = wa; const __CLPK_integer ltau = m > n ? n : m; __CLPK_integer lwork = -1; __CLPK_integer info = 0; double* work; if (pivot) { assert( lipvt >= n ); if (sizeof(__CLPK_integer) != sizeof(ipvt[0])) { jpvt = malloc(n*sizeof(__CLPK_integer)); } else { /* __CLPK_integer is actually an int, just do a cast */ jpvt = (__CLPK_integer *)ipvt; } /* set all columns free */ memset(jpvt, 0, sizeof(int)*n); } /* query optimal size of work */ lwork = -1; if (pivot) { dgeqp3_(&m_,&n_,a,&lda_,jpvt,tau,tau,&lwork,&info); lwork = (int)tau[0]; assert( lwork >= 3*n+1 ); } else { dgeqrf_(&m_,&n_,a,&lda_,tau,tau,&lwork,&info); lwork = (int)tau[0]; assert( lwork >= 1 && lwork >= n ); } assert( info == 0 ); /* alloc work area */ work = (double *)malloc(sizeof(double)*lwork); assert(work != NULL); /* set acnorm first (from the doc of qrfac, acnorm may point to the same area as rdiag) */ if (acnorm != rdiag) { for (j = 0; j < n; ++j) { acnorm[j] = __cminpack_enorm__(m, &a[j * lda]); } } /* QR decomposition */ if (pivot) { dgeqp3_(&m_,&n_,a,&lda_,jpvt,tau,work,&lwork,&info); } else { dgeqrf_(&m_,&n_,a,&lda_,tau,work,&lwork,&info); } assert(info == 0); /* set rdiag, before the diagonal is replaced */ memset(rdiag, 0, sizeof(double)*n); for(i=0 ; i rdiag[kmax]) { kmax = k; } } if (kmax != j) { for (i = 0; i < m; ++i) { temp = a[i + j * lda]; a[i + j * lda] = a[i + kmax * lda]; a[i + kmax * lda] = temp; } rdiag[kmax] = rdiag[j]; wa[kmax] = wa[j]; k = ipvt[j]; ipvt[j] = ipvt[kmax]; ipvt[kmax] = k; } } /* compute the householder transformation to reduce the */ /* j-th column of a to a multiple of the j-th unit vector. */ ajnorm = __cminpack_enorm__(m - (j+1) + 1, &a[j + j * lda]); if (ajnorm != 0.) { if (a[j + j * lda] < 0.) { ajnorm = -ajnorm; } for (i = j; i < m; ++i) { a[i + j * lda] /= ajnorm; } a[j + j * lda] += 1.; /* apply the transformation to the remaining columns */ /* and update the norms. */ jp1 = j + 1; if (n > jp1) { for (k = jp1; k < n; ++k) { sum = 0.; for (i = j; i < m; ++i) { sum += a[i + j * lda] * a[i + k * lda]; } temp = sum / a[j + j * lda]; for (i = j; i < m; ++i) { a[i + k * lda] -= temp * a[i + j * lda]; } if (pivot && rdiag[k] != 0.) { temp = a[j + k * lda] / rdiag[k]; /* Computing MAX */ d1 = 1. - temp * temp; rdiag[k] *= sqrt((max((real)0.,d1))); /* Computing 2nd power */ d1 = rdiag[k] / wa[k]; if (p05 * (d1 * d1) <= epsmch) { rdiag[k] = __cminpack_enorm__(m - (j+1), &a[jp1 + k * lda]); wa[k] = rdiag[k]; } } } } } rdiag[j] = -ajnorm; } /* last card of subroutine qrfac. */ #endif /* !USE_LAPACK */ } /* qrfac_ */