1 /* adapted from DQRDC of LINPACK */
5 #define SIGN(a, b) ((b) >= 0.0 ? fabs(a) : -fabs(a))
8 NORM2(int i
, int j
, int n
, double **x
)
11 double maxx
, sum
, temp
;
13 for (k
= i
, maxx
= 0.0; k
< n
; k
++) {
15 if (maxx
< temp
) maxx
= temp
;
17 if (maxx
== 0.0) return(0.0);
19 for (k
= i
, sum
= 0.0; k
< n
; k
++) {
20 temp
= x
[k
][j
] / maxx
;
23 return(maxx
* sqrt(sum
));
28 DOT(int i
, int j
, int k
, int n
, double **x
)
33 for (l
= i
, sum
= 0.0; l
< n
; l
++) sum
+= x
[l
][j
] * x
[l
][k
];
38 AXPY(int i
, int j
, int k
, int n
,
42 for (l
= i
; l
< n
; l
++) {
43 x
[l
][k
] = a
* x
[l
][j
] + x
[l
][k
];
48 SCALE(int i
, int j
, int n
, double a
, double **x
)
51 for (k
= i
; k
< n
; k
++) {
57 SWAP(int i
, int j
, int n
, double **a
)
61 for (k
= 0; k
< n
; k
++) {
69 qrdecomp(double **x
, int n
, int p
,
70 double **v
, int *jpvt
, int pivot
)
72 int i
,j
,k
,jp
,l
,lp1
,lup
,maxj
;
73 double maxnrm
,tt
,*qraux
,*work
;
83 * compute the norms of the free columns.
86 for (j
= 0; j
< p
; j
++) {
88 qraux
[j
] = NORM2(0, j
, n
, x
);
92 * perform the householder reduction of x.
94 lup
= (n
< p
) ? n
: p
;
95 for (l
= 0; l
< lup
; l
++) {
98 * locate the column of largest norm and bring it
99 * into the pivot position.
103 for (j
= l
; j
< p
; j
++)
104 if (qraux
[j
]>maxnrm
) {
110 qraux
[maxj
] = qraux
[l
];
111 work
[maxj
] = work
[l
];
113 jpvt
[maxj
] = jpvt
[l
];
120 * compute the householder transformation for column l.
122 nrmxl
= NORM2(l
, l
, n
, x
);
125 nrmxl
= SIGN(nrmxl
, x
[l
][l
]);
126 SCALE(l
, l
, n
, 1.0 / nrmxl
, x
);
127 x
[l
][l
] = 1.0+x
[l
][l
];
129 * apply the transformation to the remaining columns,
130 * updating the norms.
133 for (j
= lp1
; j
< p
; j
++) {
134 t
= -DOT(l
, l
, j
, n
, x
) / x
[l
][l
];
135 AXPY(l
, l
, j
, n
, t
, x
);
138 tt
= 1.0-(fabs(x
[l
][j
])/qraux
[j
])*(fabs(x
[l
][j
])/qraux
[j
]);
139 if (tt
< 0.0) tt
= 0.0;
141 tt
= 1.0+0.05*tt
*(qraux
[j
]/work
[j
])*(qraux
[j
]/work
[j
]);
143 qraux
[j
] = qraux
[j
]*sqrt(t
);
145 qraux
[j
] = NORM2(l
+1, j
, n
, x
);
151 * save the transformation.
159 /* copy over the upper triangle of a */
160 for (i
= 0; i
< p
; i
++) {
161 for (j
= 0; j
< i
; j
++) v
[i
][j
] = 0.0;
162 for (j
= i
; j
< p
; j
++) {
167 /* accumulate the Q transformation -- assumes p <= n */
168 for (i
= 0; i
< p
; i
++) {
170 for (k
= 0; k
< i
; k
++) x
[k
][i
] = 0.0;
172 for (i
= p
- 1; i
>= 0; i
--) {
173 if (i
== n
- 1) x
[i
][i
] = 1.0;
175 for (k
= i
; k
< n
; k
++) x
[k
][i
] = -x
[k
][i
];
178 for (j
= i
- 1; j
>= 0; j
--) {
179 if (x
[j
][j
] != 0.0) {
180 t
= -DOT(j
, j
, i
, n
, x
) / x
[j
][j
];
181 AXPY(j
, j
, i
, n
, t
, x
);