File Coverage

las2.c
Criterion Covered Total %
statement 496 631 78.6
branch 243 400 60.7
condition n/a
subroutine n/a
pod n/a
total 739 1031 71.6


line stmt bran cond sub pod time code
1             #include
2             /*
3             Copyright © 2002, University of Tennessee Research Foundation.
4             All rights reserved.
5              
6             Redistribution and use in source and binary forms, with or without
7             modification, are permitted provided that the following conditions are met:
8              
9             * Redistributions of source code must retain the above copyright notice, this
10             list of conditions and the following disclaimer.
11              
12             Redistributions in binary form must reproduce the above copyright notice,
13             this list of conditions and the following disclaimer in the documentation
14             and/or other materials provided with the distribution.
15              
16             * Neither the name of the University of Tennessee nor the names of its
17             contributors may be used to endorse or promote products derived from this
18             software without specific prior written permission.
19              
20             THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21             AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22             IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23             ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24             LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25             CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26             SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27             INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28             CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29             ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30             POSSIBILITY OF SUCH DAMAGE.
31             */
32             /*
33             * Modified by moocow for PDL::SVDLIBC distribution
34             */
35              
36             #include
37             #include
38             #include
39             #include
40             #include
41             #include
42             #include "svdlib.h"
43             #include "svdutil.h"
44              
45             #define MAXLL 2
46              
47             #define LMTNW 100000000 /* max. size of working area allowed */
48              
49             enum storeVals {STORQ = 1, RETRQ, STORP, RETRP};
50              
51             static char *error_msg[] = { /* error messages used by function *
52             * check_parameters */
53             NULL,
54             "",
55             "ENDL MUST BE LESS THAN ENDR",
56             "REQUESTED DIMENSIONS CANNOT EXCEED NUM ITERATIONS",
57             "ONE OF YOUR DIMENSIONS IS LESS THAN OR EQUAL TO ZERO",
58             "NUM ITERATIONS (NUMBER OF LANCZOS STEPS) IS INVALID",
59             "REQUESTED DIMENSIONS (NUMBER OF EIGENPAIRS DESIRED) IS INVALID",
60             "6*N+4*ITERATIONS+1 + ITERATIONS*ITERATIONS CANNOT EXCEED NW",
61             "6*N+4*ITERATIONS+1 CANNOT EXCEED NW", NULL};
62              
63             double **LanStore, *OPBTemp;
64             double eps, eps1, reps, eps34;
65             __SVDLIBC_LONG ierr;
66             /*
67             double rnm, anorm, tol;
68             FILE *fp_out1, *fp_out2;
69             */
70              
71             void purge(__SVDLIBC_LONG n, __SVDLIBC_LONG ll, double *r, double *q, double *ra,
72             double *qa, double *wrk, double *eta, double *oldeta, __SVDLIBC_LONG step,
73             double *rnmp, double tol);
74             void ortbnd(double *alf, double *eta, double *oldeta, double *bet, __SVDLIBC_LONG step,
75             double rnm);
76             double startv(SMat A, double *wptr[], __SVDLIBC_LONG step, __SVDLIBC_LONG n);
77             void store(__SVDLIBC_LONG, __SVDLIBC_LONG, __SVDLIBC_LONG, double *);
78             void imtql2(__SVDLIBC_LONG, __SVDLIBC_LONG, double *, double *, double *);
79             void imtqlb(__SVDLIBC_LONG n, double d[], double e[], double bnd[]);
80             void write_header(__SVDLIBC_LONG, __SVDLIBC_LONG, double, double, __SVDLIBC_LONG, double, __SVDLIBC_LONG, __SVDLIBC_LONG,
81             __SVDLIBC_LONG);
82             __SVDLIBC_LONG check_parameters(SMat A, __SVDLIBC_LONG dimensions, __SVDLIBC_LONG iterations,
83             double endl, double endr, __SVDLIBC_LONG vectors);
84             int lanso(SMat A, __SVDLIBC_LONG iterations, __SVDLIBC_LONG dimensions, double endl,
85             double endr, double *ritz, double *bnd, double *wptr[],
86             __SVDLIBC_LONG *neigp, __SVDLIBC_LONG n);
87             __SVDLIBC_LONG ritvec(__SVDLIBC_LONG n, SMat A, SVDRec R, double kappa, double *ritz,
88             double *bnd, double *alf, double *bet, double *w2,
89             __SVDLIBC_LONG steps, __SVDLIBC_LONG neig);
90             __SVDLIBC_LONG lanczos_step(SMat A, __SVDLIBC_LONG first, __SVDLIBC_LONG last, double *wptr[],
91             double *alf, double *eta, double *oldeta,
92             double *bet, __SVDLIBC_LONG *ll, __SVDLIBC_LONG *enough, double *rnmp,
93             double *tolp, __SVDLIBC_LONG n);
94             void stpone(SMat A, double *wrkptr[], double *rnmp, double *tolp, __SVDLIBC_LONG n);
95             __SVDLIBC_LONG error_bound(__SVDLIBC_LONG *, double, double, double *, double *, __SVDLIBC_LONG step,
96             double tol);
97             void machar(__SVDLIBC_LONG *ibeta, __SVDLIBC_LONG *it, __SVDLIBC_LONG *irnd, __SVDLIBC_LONG *machep, __SVDLIBC_LONG *negep);
98              
99             /***********************************************************************
100             * *
101             * main() *
102             * Sparse SVD(A) via Eigensystem of A'A symmetric Matrix *
103             * (double precision) *
104             * *
105             ***********************************************************************/
106             /***********************************************************************
107              
108             Description
109             -----------
110              
111             This sample program uses landr to compute singular triplets of A via
112             the equivalent symmetric eigenvalue problem
113              
114             B x = lambda x, where x' = (u',v'), lambda = sigma**2,
115             where sigma is a singular value of A,
116            
117             B = A'A , and A is m (nrow) by n (ncol) (nrow >> ncol),
118            
119             so that {u,sqrt(lambda),v} is a singular triplet of A.
120             (A' = transpose of A)
121            
122             User supplied routines: svd_opa, opb, store, timer
123            
124             svd_opa( x,y) takes an n-vector x and returns A*x in y.
125             svd_opb(ncol,x,y) takes an n-vector x and returns B*x in y.
126            
127             Based on operation flag isw, store(n,isw,j,s) stores/retrieves
128             to/from storage a vector of length n in s.
129            
130             User should edit timer() with an appropriate call to an intrinsic
131             timing routine that returns elapsed user time.
132              
133              
134             External parameters
135             -------------------
136              
137             Defined and documented in las2.h
138              
139              
140             Local parameters
141             ----------------
142              
143             (input)
144             endl left end of interval containing unwanted eigenvalues of B
145             endr right end of interval containing unwanted eigenvalues of B
146             kappa relative accuracy of ritz values acceptable as eigenvalues
147             of B
148             vectors is not equal to 1
149             r work array
150             n dimension of the eigenproblem for matrix B (ncol)
151             dimensions upper limit of desired number of singular triplets of A
152             iterations upper limit of desired number of Lanczos steps
153             nnzero number of nonzeros in A
154             vectors 1 indicates both singular values and singular vectors are
155             wanted and they can be found in output file lav2;
156             0 indicates only singular values are wanted
157            
158             (output)
159             ritz array of ritz values
160             bnd array of error bounds
161             d array of singular values
162             memory total memory allocated in bytes to solve the B-eigenproblem
163              
164              
165             Functions used
166             --------------
167              
168             BLAS svd_daxpy, svd_dscal, svd_ddot
169             USER svd_opa, svd_opb, timer
170             MISC write_header, check_parameters
171             LAS2 landr
172              
173              
174             Precision
175             ---------
176              
177             All floating-point calculations are done in double precision;
178             variables are declared as __SVDLIBC_LONG and double.
179              
180              
181             LAS2 development
182             ----------------
183              
184             LAS2 is a C translation of the Fortran-77 LAS2 from the SVDPACK
185             library written by Michael W. Berry, University of Tennessee,
186             Dept. of Computer Science, 107 Ayres Hall, Knoxville, TN, 37996-1301
187              
188             31 Jan 1992: Date written
189              
190             Theresa H. Do
191             University of Tennessee
192             Dept. of Computer Science
193             107 Ayres Hall
194             Knoxville, TN, 37996-1301
195             internet: tdo@cs.utk.edu
196              
197             ***********************************************************************/
198              
199             /***********************************************************************
200             * *
201             * check_parameters() *
202             * *
203             ***********************************************************************/
204             /***********************************************************************
205              
206             Description
207             -----------
208             Function validates input parameters and returns error code (__SVDLIBC_LONG)
209              
210             Parameters
211             ----------
212             (input)
213             dimensions upper limit of desired number of eigenpairs of B
214             iterations upper limit of desired number of lanczos steps
215             n dimension of the eigenproblem for matrix B
216             endl left end of interval containing unwanted eigenvalues of B
217             endr right end of interval containing unwanted eigenvalues of B
218             vectors 1 indicates both eigenvalues and eigenvectors are wanted
219             and they can be found in lav2; 0 indicates eigenvalues only
220             nnzero number of nonzero elements in input matrix (matrix A)
221            
222             ***********************************************************************/
223              
224 10           __SVDLIBC_LONG check_parameters(SMat A, __SVDLIBC_LONG dimensions, __SVDLIBC_LONG iterations,
225             double endl, double endr, __SVDLIBC_LONG vectors) {
226             __SVDLIBC_LONG error_index;
227 10           error_index = 0;
228              
229 10 50         if (endl >/*=*/ endr) error_index = 2;
230 10 50         else if (dimensions > iterations) error_index = 3;
231 10 50         else if (A->cols <= 0 || A->rows <= 0) error_index = 4;
    50          
232             /*else if (n > A->cols || n > A->rows) error_index = 1;*/
233 10 50         else if (iterations <= 0 || iterations > A->cols || iterations > A->rows)
    50          
    50          
234 0           error_index = 5;
235 10 50         else if (dimensions <= 0 || dimensions > iterations) error_index = 6;
    50          
236 10 50         if (error_index)
237 0           svd_error("svdLAS2 parameter error: %s\n", error_msg[error_index]);
238 10           return(error_index);
239             }
240              
241             /***********************************************************************
242             * *
243             * write_header() *
244             * Function writes out header of output file containing ritz values *
245             * *
246             ***********************************************************************/
247              
248 0           void write_header(__SVDLIBC_LONG iterations, __SVDLIBC_LONG dimensions, double endl, double endr,
249             __SVDLIBC_LONG vectors, double kappa, __SVDLIBC_LONG nrow, __SVDLIBC_LONG ncol,
250             __SVDLIBC_LONG vals) {
251 0           printf("SOLVING THE [A^TA] EIGENPROBLEM\n");
252 0           printf("NO. OF ROWS = %6ld\n", nrow);
253 0           printf("NO. OF COLUMNS = %6ld\n", ncol);
254 0           printf("NO. OF NON-ZERO VALUES = %6ld\n", vals);
255 0           printf("MATRIX DENSITY = %6.2f%%\n",
256 0           ((float) vals / nrow) * 100 / ncol);
257             /* printf("ORDER OF MATRIX A = %5ld\n", n); */
258 0           printf("MAX. NO. OF LANCZOS STEPS = %6ld\n", iterations);
259 0           printf("MAX. NO. OF EIGENPAIRS = %6ld\n", dimensions);
260 0           printf("LEFT END OF THE INTERVAL = %9.2E\n", endl);
261 0           printf("RIGHT END OF THE INTERVAL = %9.2E\n", endr);
262 0           printf("KAPPA = %9.2E\n", kappa);
263             /* printf("WANT S-VECTORS? [T/F] = %c\n", (vectors) ? 'T' : 'F'); */
264 0           printf("\n");
265 0           return;
266             }
267              
268              
269             /***********************************************************************
270             * *
271             * landr() *
272             * Lanczos algorithm with selective orthogonalization *
273             * Using Simon's Recurrence *
274             * (double precision) *
275             * *
276             ***********************************************************************/
277             /***********************************************************************
278              
279             Description
280             -----------
281              
282             landr() is the LAS2 driver routine that, upon entry,
283             (1) checks for the validity of input parameters of the
284             B-eigenproblem
285             (2) determines several machine constants
286             (3) makes a Lanczos run
287             (4) calculates B-eigenvectors (singular vectors of A) if requested
288             by user
289              
290              
291             arguments
292             ---------
293              
294             (input)
295             n dimension of the eigenproblem for A'A
296             iterations upper limit of desired number of Lanczos steps
297             dimensions upper limit of desired number of eigenpairs
298             nnzero number of nonzeros in matrix A
299             endl left end of interval containing unwanted eigenvalues of B
300             endr right end of interval containing unwanted eigenvalues of B
301             vectors 1 indicates both eigenvalues and eigenvectors are wanted
302             and they can be found in output file lav2;
303             0 indicates only eigenvalues are wanted
304             kappa relative accuracy of ritz values acceptable as eigenvalues
305             of B (singular values of A)
306             r work array
307              
308             (output)
309             j number of Lanczos steps actually taken
310             neig number of ritz values stabilized
311             ritz array to hold the ritz values
312             bnd array to hold the error bounds
313              
314              
315             External parameters
316             -------------------
317              
318             Defined and documented in las2.h
319              
320              
321             local parameters
322             -------------------
323              
324             ibeta radix for the floating-point representation
325             it number of base ibeta digits in the floating-point significand
326             irnd floating-point addition rounded or chopped
327             machep machine relative precision or round-off error
328             negeps largest negative integer
329             wptr array of pointers each pointing to a work space
330              
331              
332             Functions used
333             --------------
334              
335             MISC svd_dmax, machar, check_parameters
336             LAS2 ritvec, lanso
337              
338             ***********************************************************************/
339              
340 0           SVDRec svdLAS2A(SMat A, __SVDLIBC_LONG dimensions) {
341 0           double end[2] = {-1.0e-30, 1.0e-30};
342 0           double kappa = 1e-6;
343 0 0         if (!A) {
344 0           svd_error("svdLAS2A called with NULL array\n");
345 0           return NULL;
346             }
347 0           return svdLAS2(A, dimensions, 0, end, kappa);
348             }
349              
350              
351 10           SVDRec svdLAS2(SMat A, __SVDLIBC_LONG dimensions, __SVDLIBC_LONG iterations, double end[2],
352             double kappa) {
353 10           char transpose = FALSE;
354             __SVDLIBC_LONG ibeta, it, irnd, machep, negep, n, i, steps, nsig, neig, m;
355             double *wptr[10], *ritz, *bnd;
356 10           SVDRec R = NULL;
357 10           ierr = 0; // reset the global error flag
358            
359 10           svdResetCounters();
360              
361 10           m = svd_imin(A->rows, A->cols);
362 10 50         if (dimensions <= 0 || dimensions > m)
    100          
363 7           dimensions = m;
364 10 50         if (iterations <= 0 || iterations > m)
    50          
365 10           iterations = m;
366 10 50         if (iterations < dimensions) iterations = dimensions;
367              
368             /* Write output header */
369 10 50         if (SVDVerbosity > 0)
370 0           write_header(iterations, dimensions, end[0], end[1], TRUE, kappa, A->rows,
371             A->cols, A->vals);
372              
373             /* Check parameters */
374 10 50         if (check_parameters(A, dimensions, iterations, end[0], end[1], TRUE))
375 0           return NULL;
376              
377             #if 0
378             /* Fri, 24 Jul 2015 11:31:27 +0200 moocow
379             * + disable transposition for PDL::SVDLIBC, since we're getting segfaults whenever this code runs
380             */
381             /* If A is wide, the SVD is computed on its transpose for speed. */
382             if (A->cols >= A->rows * 1.2) {
383             if (SVDVerbosity > 0) printf("TRANSPOSING THE MATRIX FOR SPEED\n");
384             transpose = TRUE;
385             A = svdTransposeS(A);
386             }
387             #endif
388              
389 10           n = A->cols;
390             /* Compute machine precision */
391 10           machar(&ibeta, &it, &irnd, &machep, &negep);
392 10           eps1 = eps * sqrt((double) n);
393 10           reps = sqrt(eps);
394 10           eps34 = reps * sqrt(reps);
395              
396             /* Allocate temporary space. */
397 10 50         if (!(wptr[0] = svd_doubleArray(n, TRUE, "las2: wptr[0]"))) goto abort;
398 10 50         if (!(wptr[1] = svd_doubleArray(n, FALSE, "las2: wptr[1]"))) goto abort;
399 10 50         if (!(wptr[2] = svd_doubleArray(n, FALSE, "las2: wptr[2]"))) goto abort;
400 10 50         if (!(wptr[3] = svd_doubleArray(n, FALSE, "las2: wptr[3]"))) goto abort;
401 10 50         if (!(wptr[4] = svd_doubleArray(n, FALSE, "las2: wptr[4]"))) goto abort;
402 10 50         if (!(wptr[5] = svd_doubleArray(n, FALSE, "las2: wptr[5]"))) goto abort;
403 10 50         if (!(wptr[6] = svd_doubleArray(iterations, FALSE, "las2: wptr[6]")))
404 0           goto abort;
405 10 50         if (!(wptr[7] = svd_doubleArray(iterations, FALSE, "las2: wptr[7]")))
406 0           goto abort;
407 10 50         if (!(wptr[8] = svd_doubleArray(iterations, FALSE, "las2: wptr[8]")))
408 0           goto abort;
409 10 50         if (!(wptr[9] = svd_doubleArray(iterations + 1, FALSE, "las2: wptr[9]")))
410 0           goto abort;
411             /* Calloc may be unnecessary: */
412 10 50         if (!(ritz = svd_doubleArray(iterations + 1, TRUE, "las2: ritz")))
413 0           goto abort;
414             /* Calloc may be unnecessary: */
415 10 50         if (!(bnd = svd_doubleArray(iterations + 1, TRUE, "las2: bnd")))
416 0           goto abort;
417 10           memset(bnd, 127, (iterations + 1) * sizeof(double));
418              
419 10 50         if (!(LanStore = (double **) calloc(iterations + MAXLL, sizeof(double *))))
420 0           goto abort;
421 10 50         if (!(OPBTemp = svd_doubleArray(A->rows, FALSE, "las2: OPBTemp")))
422 0           goto abort;
423              
424             /* Actually run the lanczos thing: */
425 10           steps = lanso(A, iterations, dimensions, end[0], end[1], ritz, bnd, wptr,
426             &neig, n);
427              
428             /* Print some stuff. */
429 10 50         if (SVDVerbosity > 0) {
430 0           printf("NUMBER OF LANCZOS STEPS = %6ld\n"
431             "RITZ VALUES STABILIZED = %6ld\n", steps + 1, neig);
432             }
433 10 50         if (SVDVerbosity > 2) {
434 0           printf("\nCOMPUTED RITZ VALUES (ERROR BNDS)\n");
435 0 0         for (i = 0; i <= steps; i++)
436 0           printf("%3ld %22.14E (%11.2E)\n", i + 1, ritz[i], bnd[i]);
437             }
438              
439 10 50         SAFE_FREE(wptr[0]);
440 10 50         SAFE_FREE(wptr[1]);
441 10 50         SAFE_FREE(wptr[2]);
442 10 50         SAFE_FREE(wptr[3]);
443 10 50         SAFE_FREE(wptr[4]);
444 10 50         SAFE_FREE(wptr[7]);
445 10 50         SAFE_FREE(wptr[8]);
446              
447             /* Compute eigenvectors */
448 10           kappa = svd_dmax(fabs(kappa), eps34);
449            
450 10           R = svdNewSVDRec();
451 10 50         if (!R) {
452 0           svd_error("svdLAS2: allocation of R failed");
453 0           goto cleanup;
454             }
455 10           R->d = /*svd_imin(nsig, dimensions)*/dimensions;
456 10           R->Ut = svdNewDMat(R->d, A->rows);
457 10           R->S = svd_doubleArray(R->d, TRUE, "las2: R->s");
458 10           R->Vt = svdNewDMat(R->d, A->cols);
459 10 50         if (!R->Ut || !R->S || !R->Vt) {
    50          
    50          
460 0           svd_error("svdLAS2: allocation of R failed");
461 0           goto cleanup;
462             }
463              
464 10           nsig = ritvec(n, A, R, kappa, ritz, bnd, wptr[6], wptr[9], wptr[5], steps,
465             neig);
466            
467 10 50         if (SVDVerbosity > 1) {
468 0           printf("\nSINGULAR VALUES: ");
469 0           svdWriteDenseArray(R->S, R->d, "-", FALSE);
470              
471 0 0         if (SVDVerbosity > 2) {
472 0           printf("\nLEFT SINGULAR VECTORS (transpose of U): ");
473 0           svdWriteDenseMatrix(R->Ut, "-", SVD_F_DT);
474              
475 0           printf("\nRIGHT SINGULAR VECTORS (transpose of V): ");
476 0           svdWriteDenseMatrix(R->Vt, "-", SVD_F_DT);
477             }
478             }
479 10 50         if (SVDVerbosity > 0) {
480 0           printf("SINGULAR VALUES FOUND = %6d\n"
481             "SIGNIFICANT VALUES = %6ld\n", R->d, nsig);
482             }
483              
484             cleanup:
485 110 100         for (i = 0; i <= 9; i++)
486 100 100         SAFE_FREE(wptr[i]);
487 10 50         SAFE_FREE(ritz);
488 10 50         SAFE_FREE(bnd);
489 10 50         if (LanStore) {
490 90 100         for (i = 0; i < iterations + MAXLL; i++)
491 80 50         SAFE_FREE(LanStore[i]);
492 10 50         SAFE_FREE(LanStore);
493             }
494 10 50         SAFE_FREE(OPBTemp);
495              
496             /* This swaps and transposes the singular matrices if A was transposed. */
497 10 50         if (R && transpose) {
    50          
498             DMat T;
499 0           svdFreeSMat(A);
500 0           T = R->Ut;
501 0           R->Ut = R->Vt;
502 0           R->Vt = T;
503             }
504              
505 10           return R;
506             abort:
507 0           svd_error("svdLAS2: fatal error, aborting");
508 10           return NULL;
509             }
510              
511              
512             /***********************************************************************
513             * *
514             * ritvec() *
515             * Function computes the singular vectors of matrix A *
516             * *
517             ***********************************************************************/
518             /***********************************************************************
519              
520             Description
521             -----------
522              
523             This function is invoked by landr() only if eigenvectors of the A'A
524             eigenproblem are desired. When called, ritvec() computes the
525             singular vectors of A and writes the result to an unformatted file.
526              
527              
528             Parameters
529             ----------
530              
531             (input)
532             nrow number of rows of A
533             steps number of Lanczos iterations performed
534             fp_out2 pointer to unformatted output file
535             n dimension of matrix A
536             kappa relative accuracy of ritz values acceptable as
537             eigenvalues of A'A
538             ritz array of ritz values
539             bnd array of error bounds
540             alf array of diagonal elements of the tridiagonal matrix T
541             bet array of off-diagonal elements of T
542             w1, w2 work space
543              
544             (output)
545             xv1 array of eigenvectors of A'A (right singular vectors of A)
546             ierr error code
547             0 for normal return from imtql2()
548             k if convergence did not occur for k-th eigenvalue in
549             imtql2()
550             nsig number of accepted ritz values based on kappa
551              
552             (local)
553             s work array which is initialized to the identity matrix
554             of order (j + 1) upon calling imtql2(). After the call,
555             s contains the orthonormal eigenvectors of the symmetric
556             tridiagonal matrix T
557              
558             Functions used
559             --------------
560              
561             BLAS svd_dscal, svd_dcopy, svd_daxpy
562             USER store
563             imtql2
564              
565             ***********************************************************************/
566              
567 10           void rotateArray(double *a, int size, int x) {
568             int i, j, n, start;
569             double t1, t2;
570 10 100         if (x == 0) return;
571 3           j = start = 0;
572 3           t1 = a[0];
573 108 100         for (i = 0; i < size; i++) {
574 105 100         n = (j >= x) ? j - x : j + size - x;
575 105           t2 = a[n];
576 105           a[n] = t1;
577 105           t1 = t2;
578 105           j = n;
579 105 100         if (j == start) {
580 21           start = ++j;
581 21           t1 = a[j];
582             }
583             }
584             }
585              
586 10           __SVDLIBC_LONG ritvec(__SVDLIBC_LONG n, SMat A, SVDRec R, double kappa, double *ritz, double *bnd,
587             double *alf, double *bet, double *w2, __SVDLIBC_LONG steps, __SVDLIBC_LONG neig) {
588             __SVDLIBC_LONG js, jsq, i, k, /*size,*/ id2, tmp, nsig, x;
589 10           double *s, *xv2, tmp0, tmp1, xnorm, *w1 = R->Vt->value[0];
590            
591 10           js = steps + 1;
592 10           jsq = js * js;
593             /*size = sizeof(double) * n;*/
594            
595 10           s = svd_doubleArray(jsq, TRUE, "ritvec: s");
596 10           xv2 = svd_doubleArray(n, FALSE, "ritvec: xv2");
597            
598             /* initialize s to an identity matrix */
599 70 100         for (i = 0; i < jsq; i+= (js+1)) s[i] = 1.0;
600 10           svd_dcopy(js, alf, 1, w1, -1);
601 10           svd_dcopy(steps, &bet[1], 1, &w2[1], -1);
602            
603             /* on return from imtql2(), w1 contains eigenvalues in ascending
604             * order and s contains the corresponding eigenvectors */
605 10           imtql2(js, js, w1, w2, s);
606            
607             /*fwrite((char *)&n, sizeof(n), 1, fp_out2);
608             fwrite((char *)&js, sizeof(js), 1, fp_out2);
609             fwrite((char *)&kappa, sizeof(kappa), 1, fp_out2);*/
610             /*id = 0;*/
611 10           nsig = 0;
612              
613 10 50         if (ierr) {
614 0           R->d = 0;
615             } else {
616 10           x = 0;
617 10           id2 = jsq - js;
618 70 100         for (k = 0; k < js; k++) {
619 60           tmp = id2;
620 60 50         if (bnd[k] <= kappa * fabs(ritz[k]) && k > js-neig-1) {
    50          
621 60 100         if (--x < 0) x = R->d - 1;
622 60           w1 = R->Vt->value[x];
623 480 100         for (i = 0; i < n; i++) w1[i] = 0.0;
624 420 100         for (i = 0; i < js; i++) {
625 360           store(n, RETRQ, i, w2);
626 360           svd_daxpy(n, s[tmp], w2, 1, w1, 1);
627 360           tmp -= js;
628             }
629             /*fwrite((char *)w1, size, 1, fp_out2);*/
630            
631             /* store the w1 vector row-wise in array xv1;
632             * size of xv1 is (steps+1) * (nrow+ncol) elements
633             * and each vector, even though only ncol __SVDLIBC_LONG,
634             * will have (nrow+ncol) elements in xv1.
635             * It is as if xv1 is a 2-d array (steps+1) by
636             * (nrow+ncol) and each vector occupies a row */
637              
638             /* j is the index in the R arrays, which are sorted by high to low
639             singular values. */
640            
641             /*for (i = 0; i < n; i++) R->Vt->value[x]xv1[id++] = w1[i];*/
642             /*id += nrow;*/
643 60           nsig++;
644             }
645 60           id2++;
646             }
647 10 50         SAFE_FREE(s);
648              
649             /* Rotate the singular vectors and values. */
650             /* x is now the location of the highest singular value. */
651 10           rotateArray(R->Vt->value[0], R->Vt->rows * R->Vt->cols,
652 10           x * R->Vt->cols);
653 10           R->d = svd_imin(R->d, nsig);
654 67 100         for (x = 0; x < R->d; x++) {
655             /* multiply by matrix B first */
656 57           svd_opb(A, R->Vt->value[x], xv2, OPBTemp);
657 57           tmp0 = svd_ddot(n, R->Vt->value[x], 1, xv2, 1);
658 57           svd_daxpy(n, -tmp0, R->Vt->value[x], 1, xv2, 1);
659 57           tmp0 = sqrt(tmp0);
660 57           xnorm = sqrt(svd_ddot(n, xv2, 1, xv2, 1));
661            
662             /* multiply by matrix A to get (scaled) left s-vector */
663 57           svd_opa(A, R->Vt->value[x], R->Ut->value[x]);
664 57           tmp1 = 1.0 / tmp0;
665 57           svd_dscal(A->rows, tmp1, R->Ut->value[x], 1);
666 57           xnorm *= tmp1;
667 57           bnd[i] = xnorm;
668 57           R->S[x] = tmp0;
669             }
670             }
671              
672 10 50         SAFE_FREE(s);
673 10 50         SAFE_FREE(xv2);
674 10           return nsig;
675             }
676              
677             /***********************************************************************
678             * *
679             * lanso() *
680             * *
681             ***********************************************************************/
682             /***********************************************************************
683              
684             Description
685             -----------
686              
687             Function determines when the restart of the Lanczos algorithm should
688             occur and when it should terminate.
689              
690             Arguments
691             ---------
692              
693             (input)
694             n dimension of the eigenproblem for matrix B
695             iterations upper limit of desired number of lanczos steps
696             dimensions upper limit of desired number of eigenpairs
697             endl left end of interval containing unwanted eigenvalues
698             endr right end of interval containing unwanted eigenvalues
699             ritz array to hold the ritz values
700             bnd array to hold the error bounds
701             wptr array of pointers that point to work space:
702             wptr[0]-wptr[5] six vectors of length n
703             wptr[6] array to hold diagonal of the tridiagonal matrix T
704             wptr[9] array to hold off-diagonal of T
705             wptr[7] orthogonality estimate of Lanczos vectors at
706             step j
707             wptr[8] orthogonality estimate of Lanczos vectors at
708             step j-1
709              
710             (output)
711             j number of Lanczos steps actually taken
712             neig number of ritz values stabilized
713             ritz array to hold the ritz values
714             bnd array to hold the error bounds
715             ierr (globally declared) error flag
716             ierr = 8192 if stpone() fails to find a starting vector
717             ierr = k if convergence did not occur for k-th eigenvalue
718             in imtqlb()
719             ierr = 0 otherwise
720              
721              
722             Functions used
723             --------------
724              
725             LAS stpone, error_bound, lanczos_step
726             MISC svd_dsort2
727             UTILITY svd_imin, svd_imax
728              
729             ***********************************************************************/
730              
731 10           int lanso(SMat A, __SVDLIBC_LONG iterations, __SVDLIBC_LONG dimensions, double endl,
732             double endr, double *ritz, double *bnd, double *wptr[],
733             __SVDLIBC_LONG *neigp, __SVDLIBC_LONG n) {
734             double *alf, *eta, *oldeta, *bet, *wrk, rnm, tol;
735 10           __SVDLIBC_LONG ll, first, last, ENOUGH, id2, id3, i, l, neig, j = 0, intro = 0;
736            
737 10           alf = wptr[6];
738 10           eta = wptr[7];
739 10           oldeta = wptr[8];
740 10           bet = wptr[9];
741 10           wrk = wptr[5];
742            
743             /* take the first step */
744 10           stpone(A, wptr, &rnm, &tol, n);
745 10 50         if (!rnm || ierr) return 0;
    50          
746 10           eta[0] = eps1;
747 10           oldeta[0] = eps1;
748 10           ll = 0;
749 10           first = 1;
750 10           last = svd_imin(dimensions + svd_imax(8, dimensions), iterations);
751 10           ENOUGH = FALSE;
752             /*id1 = 0;*/
753 20 100         while (/*id1 < dimensions && */!ENOUGH) {
754 10 50         if (rnm <= tol) rnm = 0.0;
755            
756             /* the actual lanczos loop */
757 10           j = lanczos_step(A, first, last, wptr, alf, eta, oldeta, bet, &ll,
758             &ENOUGH, &rnm, &tol, n);
759 10 50         if (ENOUGH) j = j - 1;
760 10           else j = last - 1;
761 10           first = j + 1;
762 10           bet[j+1] = rnm;
763            
764             /* analyze T */
765 10           l = 0;
766 20 50         for (id2 = 0; id2 < j; id2++) {
767 20 100         if (l > j) break;
768 60 100         for (i = l; i <= j; i++) if (!bet[i+1]) break;
    50          
769 10 50         if (i > j) i = j;
770            
771             /* now i is at the end of an unreduced submatrix */
772 10           svd_dcopy(i-l+1, &alf[l], 1, &ritz[l], -1);
773 10           svd_dcopy(i-l, &bet[l+1], 1, &wrk[l+1], -1);
774            
775 10           imtqlb(i-l+1, &ritz[l], &wrk[l], &bnd[l]);
776            
777 10 50         if (ierr) {
778 0           svd_error("svdLAS2: imtqlb failed to converge (ierr = %ld)\n", ierr);
779 0           svd_error(" l = %ld i = %ld\n", l, i);
780 0 0         for (id3 = l; id3 <= i; id3++)
781 0           svd_error(" %ld %lg %lg %lg\n",
782 0           id3, ritz[id3], wrk[id3], bnd[id3]);
783             }
784 70 100         for (id3 = l; id3 <= i; id3++)
785 60           bnd[id3] = rnm * fabs(bnd[id3]);
786 10           l = i + 1;
787             }
788            
789             /* sort eigenvalues into increasing order */
790 10           svd_dsort2((j+1) / 2, j + 1, ritz, bnd);
791              
792             /* for (i = 0; i < iterations; i++)
793             printf("%f ", ritz[i]);
794             printf("\n"); */
795            
796             /* massage error bounds for very close ritz values */
797 10           neig = error_bound(&ENOUGH, endl, endr, ritz, bnd, j, tol);
798 10           *neigp = neig;
799            
800             /* should we stop? */
801 10 50         if (neig < dimensions) {
802 0 0         if (!neig) {
803 0           last = first + 9;
804 0           intro = first;
805 0           } else last = first + svd_imax(3, 1 + ((j - intro) * (dimensions-neig)) /
806             neig);
807 0           last = svd_imin(last, iterations);
808 10           } else ENOUGH = TRUE;
809 10 50         ENOUGH = ENOUGH || first >= iterations;
    0          
810             /* id1++; */
811             /* printf("id1=%d dimen=%d first=%d\n", id1, dimensions, first); */
812             }
813 10           store(n, STORQ, j, wptr[1]);
814 10           return j;
815             }
816              
817              
818             /***********************************************************************
819             * *
820             * lanczos_step() *
821             * *
822             ***********************************************************************/
823             /***********************************************************************
824              
825             Description
826             -----------
827              
828             Function embodies a single Lanczos step
829              
830             Arguments
831             ---------
832              
833             (input)
834             n dimension of the eigenproblem for matrix B
835             first start of index through loop
836             last end of index through loop
837             wptr array of pointers pointing to work space
838             alf array to hold diagonal of the tridiagonal matrix T
839             eta orthogonality estimate of Lanczos vectors at step j
840             oldeta orthogonality estimate of Lanczos vectors at step j-1
841             bet array to hold off-diagonal of T
842             ll number of intitial Lanczos vectors in local orthog.
843             (has value of 0, 1 or 2)
844             enough stop flag
845              
846             Functions used
847             --------------
848              
849             BLAS svd_ddot, svd_dscal, svd_daxpy, svd_datx, svd_dcopy
850             USER store
851             LAS purge, ortbnd, startv
852             UTILITY svd_imin, svd_imax
853              
854             ***********************************************************************/
855              
856 10           __SVDLIBC_LONG lanczos_step(SMat A, __SVDLIBC_LONG first, __SVDLIBC_LONG last, double *wptr[],
857             double *alf, double *eta, double *oldeta,
858             double *bet, __SVDLIBC_LONG *ll, __SVDLIBC_LONG *enough, double *rnmp,
859             double *tolp, __SVDLIBC_LONG n) {
860 10           double t, *mid, rnm = *rnmp, tol = *tolp, anorm;
861             __SVDLIBC_LONG i, j;
862              
863 60 100         for (j=first; j
864 50           mid = wptr[2];
865 50           wptr[2] = wptr[1];
866 50           wptr[1] = mid;
867 50           mid = wptr[3];
868 50           wptr[3] = wptr[4];
869 50           wptr[4] = mid;
870              
871 50           store(n, STORQ, j-1, wptr[2]);
872 50 100         if (j-1 < MAXLL) store(n, STORP, j-1, wptr[4]);
873 50           bet[j] = rnm;
874              
875             /* restart if invariant subspace is found */
876 50 50         if (!bet[j]) {
877 0           rnm = startv(A, wptr, j, n);
878 0 0         if (ierr) return j;
879 0 0         if (!rnm) *enough = TRUE;
880             }
881 50 50         if (*enough) {
882             /* added by Doug... */
883             /* These lines fix a bug that occurs with low-rank matrices */
884 0           mid = wptr[2];
885 0           wptr[2] = wptr[1];
886 0           wptr[1] = mid;
887             /* ...added by Doug */
888 0           break;
889             }
890              
891             /* take a lanczos step */
892 50           t = 1.0 / rnm;
893 50           svd_datx(n, t, wptr[0], 1, wptr[1], 1);
894 50           svd_dscal(n, t, wptr[3], 1);
895 50           svd_opb(A, wptr[3], wptr[0], OPBTemp);
896 50           svd_daxpy(n, -rnm, wptr[2], 1, wptr[0], 1);
897 50           alf[j] = svd_ddot(n, wptr[0], 1, wptr[3], 1);
898 50           svd_daxpy(n, -alf[j], wptr[1], 1, wptr[0], 1);
899              
900             /* orthogonalize against initial lanczos vectors */
901 50 100         if (j <= MAXLL && (fabs(alf[j-1]) > 4.0 * fabs(alf[j])))
    50          
902 0           *ll = j;
903 50 50         for (i=0; i < svd_imin(*ll, j-1); i++) {
904 0           store(n, RETRP, i, wptr[5]);
905 0           t = svd_ddot(n, wptr[5], 1, wptr[0], 1);
906 0           store(n, RETRQ, i, wptr[5]);
907 0           svd_daxpy(n, -t, wptr[5], 1, wptr[0], 1);
908 0           eta[i] = eps1;
909 0           oldeta[i] = eps1;
910             }
911              
912             /* extended local reorthogonalization */
913 50           t = svd_ddot(n, wptr[0], 1, wptr[4], 1);
914 50           svd_daxpy(n, -t, wptr[2], 1, wptr[0], 1);
915 50 50         if (bet[j] > 0.0) bet[j] = bet[j] + t;
916 50           t = svd_ddot(n, wptr[0], 1, wptr[3], 1);
917 50           svd_daxpy(n, -t, wptr[1], 1, wptr[0], 1);
918 50           alf[j] = alf[j] + t;
919 50           svd_dcopy(n, wptr[0], 1, wptr[4], 1);
920 50           rnm = sqrt(svd_ddot(n, wptr[0], 1, wptr[4], 1));
921 50           anorm = bet[j] + fabs(alf[j]) + rnm;
922 50           tol = reps * anorm;
923              
924             /* update the orthogonality bounds */
925 50           ortbnd(alf, eta, oldeta, bet, j, rnm);
926              
927             /* restore the orthogonality state when needed */
928 50           purge(n, *ll, wptr[0], wptr[1], wptr[4], wptr[3], wptr[5], eta, oldeta,
929             j, &rnm, tol);
930 50 100         if (rnm <= tol) rnm = 0.0;
931             }
932 10           *rnmp = rnm;
933 10           *tolp = tol;
934 10           return j;
935             }
936              
937             /***********************************************************************
938             * *
939             * ortbnd() *
940             * *
941             ***********************************************************************/
942             /***********************************************************************
943              
944             Description
945             -----------
946              
947             Funtion updates the eta recurrence
948              
949             Arguments
950             ---------
951              
952             (input)
953             alf array to hold diagonal of the tridiagonal matrix T
954             eta orthogonality estimate of Lanczos vectors at step j
955             oldeta orthogonality estimate of Lanczos vectors at step j-1
956             bet array to hold off-diagonal of T
957             n dimension of the eigenproblem for matrix B
958             j dimension of T
959             rnm norm of the next residual vector
960             eps1 roundoff estimate for dot product of two unit vectors
961              
962             (output)
963             eta orthogonality estimate of Lanczos vectors at step j+1
964             oldeta orthogonality estimate of Lanczos vectors at step j
965              
966              
967             Functions used
968             --------------
969              
970             BLAS svd_dswap
971              
972             ***********************************************************************/
973              
974 50           void ortbnd(double *alf, double *eta, double *oldeta, double *bet, __SVDLIBC_LONG step,
975             double rnm) {
976             __SVDLIBC_LONG i;
977 50 50         if (step < 1) return;
978 50 50         if (rnm) {
979 50 100         if (step > 1) {
980 40           oldeta[0] = (bet[1] * eta[1] + (alf[0]-alf[step]) * eta[0] -
981 80           bet[step] * oldeta[0]) / rnm + eps1;
982             }
983 110 100         for (i=1; i<=step-2; i++)
984 180           oldeta[i] = (bet[i+1] * eta[i+1] + (alf[i]-alf[step]) * eta[i] +
985 120           bet[i] * eta[i-1] - bet[step] * oldeta[i])/rnm + eps1;
986             }
987 50           oldeta[step-1] = eps1;
988 50           svd_dswap(step, oldeta, 1, eta, 1);
989 50           eta[step] = eps1;
990 50           return;
991             }
992              
993             /***********************************************************************
994             * *
995             * purge() *
996             * *
997             ***********************************************************************/
998             /***********************************************************************
999              
1000             Description
1001             -----------
1002              
1003             Function examines the state of orthogonality between the new Lanczos
1004             vector and the previous ones to decide whether re-orthogonalization
1005             should be performed
1006              
1007              
1008             Arguments
1009             ---------
1010              
1011             (input)
1012             n dimension of the eigenproblem for matrix B
1013             ll number of intitial Lanczos vectors in local orthog.
1014             r residual vector to become next Lanczos vector
1015             q current Lanczos vector
1016             ra previous Lanczos vector
1017             qa previous Lanczos vector
1018             wrk temporary vector to hold the previous Lanczos vector
1019             eta state of orthogonality between r and prev. Lanczos vectors
1020             oldeta state of orthogonality between q and prev. Lanczos vectors
1021             j current Lanczos step
1022              
1023             (output)
1024             r residual vector orthogonalized against previous Lanczos
1025             vectors
1026             q current Lanczos vector orthogonalized against previous ones
1027              
1028              
1029             Functions used
1030             --------------
1031              
1032             BLAS svd_daxpy, svd_dcopy, svd_idamax, svd_ddot
1033             USER store
1034              
1035             ***********************************************************************/
1036              
1037 50           void purge(__SVDLIBC_LONG n, __SVDLIBC_LONG ll, double *r, double *q, double *ra,
1038             double *qa, double *wrk, double *eta, double *oldeta, __SVDLIBC_LONG step,
1039             double *rnmp, double tol) {
1040 50           double t, tq, tr, reps1, rnm = *rnmp;
1041             __SVDLIBC_LONG k, iteration, flag, i;
1042            
1043 50 100         if (step < ll+2) return;
1044            
1045 40           k = svd_idamax(step - (ll+1), &eta[ll], 1) + ll;
1046 40 100         if (fabs(eta[k]) > reps) {
1047 10           reps1 = eps1 / reps;
1048 10           iteration = 0;
1049 10           flag = TRUE;
1050 30 100         while (iteration < 2 && flag) {
    50          
1051 20 50         if (rnm > tol) {
1052            
1053             /* bring in a lanczos vector t and orthogonalize both
1054             * r and q against it */
1055 0           tq = 0.0;
1056 0           tr = 0.0;
1057 0 0         for (i = ll; i < step; i++) {
1058 0           store(n, RETRQ, i, wrk);
1059 0           t = -svd_ddot(n, qa, 1, wrk, 1);
1060 0           tq += fabs(t);
1061 0           svd_daxpy(n, t, wrk, 1, q, 1);
1062 0           t = -svd_ddot(n, ra, 1, wrk, 1);
1063 0           tr += fabs(t);
1064 0           svd_daxpy(n, t, wrk, 1, r, 1);
1065             }
1066 0           svd_dcopy(n, q, 1, qa, 1);
1067 0           t = -svd_ddot(n, r, 1, qa, 1);
1068 0           tr += fabs(t);
1069 0           svd_daxpy(n, t, q, 1, r, 1);
1070 0           svd_dcopy(n, r, 1, ra, 1);
1071 0           rnm = sqrt(svd_ddot(n, ra, 1, r, 1));
1072 0 0         if (tq <= reps1 && tr <= reps1 * rnm) flag = FALSE;
    0          
1073             }
1074 20           iteration++;
1075             }
1076 70 100         for (i = ll; i <= step; i++) {
1077 60           eta[i] = eps1;
1078 60           oldeta[i] = eps1;
1079             }
1080             }
1081 40           *rnmp = rnm;
1082 40           return;
1083             }
1084              
1085              
1086             /***********************************************************************
1087             * *
1088             * stpone() *
1089             * *
1090             ***********************************************************************/
1091             /***********************************************************************
1092              
1093             Description
1094             -----------
1095              
1096             Function performs the first step of the Lanczos algorithm. It also
1097             does a step of extended local re-orthogonalization.
1098              
1099             Arguments
1100             ---------
1101              
1102             (input)
1103             n dimension of the eigenproblem for matrix B
1104              
1105             (output)
1106             ierr error flag
1107             wptr array of pointers that point to work space that contains
1108             wptr[0] r[j]
1109             wptr[1] q[j]
1110             wptr[2] q[j-1]
1111             wptr[3] p
1112             wptr[4] p[j-1]
1113             wptr[6] diagonal elements of matrix T
1114              
1115              
1116             Functions used
1117             --------------
1118              
1119             BLAS svd_daxpy, svd_datx, svd_dcopy, svd_ddot, svd_dscal
1120             USER store, opb
1121             LAS startv
1122              
1123             ***********************************************************************/
1124              
1125 10           void stpone(SMat A, double *wrkptr[], double *rnmp, double *tolp, __SVDLIBC_LONG n) {
1126             double t, *alf, rnm, anorm;
1127 10           alf = wrkptr[6];
1128              
1129             /* get initial vector; default is random */
1130 10           rnm = startv(A, wrkptr, 0, n);
1131 10 50         if (rnm == 0.0 || ierr != 0) return;
    50          
1132              
1133             /* normalize starting vector */
1134 10           t = 1.0 / rnm;
1135 10           svd_datx(n, t, wrkptr[0], 1, wrkptr[1], 1);
1136 10           svd_dscal(n, t, wrkptr[3], 1);
1137              
1138             /* take the first step */
1139 10           svd_opb(A, wrkptr[3], wrkptr[0], OPBTemp);
1140 10           alf[0] = svd_ddot(n, wrkptr[0], 1, wrkptr[3], 1);
1141 10           svd_daxpy(n, -alf[0], wrkptr[1], 1, wrkptr[0], 1);
1142 10           t = svd_ddot(n, wrkptr[0], 1, wrkptr[3], 1);
1143 10           svd_daxpy(n, -t, wrkptr[1], 1, wrkptr[0], 1);
1144 10           alf[0] += t;
1145 10           svd_dcopy(n, wrkptr[0], 1, wrkptr[4], 1);
1146 10           rnm = sqrt(svd_ddot(n, wrkptr[0], 1, wrkptr[4], 1));
1147 10           anorm = rnm + fabs(alf[0]);
1148 10           *rnmp = rnm;
1149 10           *tolp = reps * anorm;
1150              
1151 10           return;
1152             }
1153              
1154             /***********************************************************************
1155             * *
1156             * startv() *
1157             * *
1158             ***********************************************************************/
1159             /***********************************************************************
1160              
1161             Description
1162             -----------
1163              
1164             Function delivers a starting vector in r and returns |r|; it returns
1165             zero if the range is spanned, and ierr is non-zero if no starting
1166             vector within range of operator can be found.
1167              
1168             Parameters
1169             ---------
1170              
1171             (input)
1172             n dimension of the eigenproblem matrix B
1173             wptr array of pointers that point to work space
1174             j starting index for a Lanczos run
1175             eps machine epsilon (relative precision)
1176              
1177             (output)
1178             wptr array of pointers that point to work space that contains
1179             r[j], q[j], q[j-1], p[j], p[j-1]
1180             ierr error flag (nonzero if no starting vector can be found)
1181              
1182             Functions used
1183             --------------
1184              
1185             BLAS svd_ddot, svd_dcopy, svd_daxpy
1186             USER svd_opb, store
1187             MISC random
1188              
1189             ***********************************************************************/
1190              
1191 10           double startv(SMat A, double *wptr[], __SVDLIBC_LONG step, __SVDLIBC_LONG n) {
1192             double rnm2, *r, t;
1193             __SVDLIBC_LONG irand;
1194             __SVDLIBC_LONG id, i;
1195              
1196             /* get initial vector; default is random */
1197 10           rnm2 = svd_ddot(n, wptr[0], 1, wptr[0], 1);
1198 10           irand = 918273 + step;
1199 10           r = wptr[0];
1200 10 50         for (id = 0; id < 3; id++) {
1201 10 50         if (id > 0 || step > 0 || rnm2 == 0)
    50          
    50          
1202 80 100         for (i = 0; i < n; i++) r[i] = svd_random2(&irand);
1203 10           svd_dcopy(n, wptr[0], 1, wptr[3], 1);
1204              
1205             /* apply operator to put r in range (essential if m singular) */
1206 10           svd_opb(A, wptr[3], wptr[0], OPBTemp);
1207 10           svd_dcopy(n, wptr[0], 1, wptr[3], 1);
1208 10           rnm2 = svd_ddot(n, wptr[0], 1, wptr[3], 1);
1209 10 50         if (rnm2 > 0.0) break;
1210             }
1211              
1212             /* fatal error */
1213 10 50         if (rnm2 <= 0.0) {
1214 0           ierr = 8192;
1215 0           return(-1);
1216             }
1217 10 50         if (step > 0) {
1218 0 0         for (i = 0; i < step; i++) {
1219 0           store(n, RETRQ, i, wptr[5]);
1220 0           t = -svd_ddot(n, wptr[3], 1, wptr[5], 1);
1221 0           svd_daxpy(n, t, wptr[5], 1, wptr[0], 1);
1222             }
1223              
1224             /* make sure q[step] is orthogonal to q[step-1] */
1225 0           t = svd_ddot(n, wptr[4], 1, wptr[0], 1);
1226 0           svd_daxpy(n, -t, wptr[2], 1, wptr[0], 1);
1227 0           svd_dcopy(n, wptr[0], 1, wptr[3], 1);
1228 0           t = svd_ddot(n, wptr[3], 1, wptr[0], 1);
1229 0 0         if (t <= eps * rnm2) t = 0.0;
1230 0           rnm2 = t;
1231             }
1232 10           return(sqrt(rnm2));
1233             }
1234              
1235             /***********************************************************************
1236             * *
1237             * error_bound() *
1238             * *
1239             ***********************************************************************/
1240             /***********************************************************************
1241              
1242             Description
1243             -----------
1244              
1245             Function massages error bounds for very close ritz values by placing
1246             a gap between them. The error bounds are then refined to reflect
1247             this.
1248              
1249              
1250             Arguments
1251             ---------
1252              
1253             (input)
1254             endl left end of interval containing unwanted eigenvalues
1255             endr right end of interval containing unwanted eigenvalues
1256             ritz array to store the ritz values
1257             bnd array to store the error bounds
1258             enough stop flag
1259              
1260              
1261             Functions used
1262             --------------
1263              
1264             BLAS svd_idamax
1265             UTILITY svd_dmin
1266              
1267             ***********************************************************************/
1268              
1269 10           __SVDLIBC_LONG error_bound(__SVDLIBC_LONG *enough, double endl, double endr,
1270             double *ritz, double *bnd, __SVDLIBC_LONG step, double tol) {
1271             __SVDLIBC_LONG mid, i, neig;
1272             double gapl, gap;
1273            
1274             /* massage error bounds for very close ritz values */
1275 10           mid = svd_idamax(step + 1, bnd, 1);
1276              
1277 60 100         for (i=((step+1) + (step-1)) / 2; i >= mid + 1; i -= 1)
1278 50 50         if (fabs(ritz[i-1] - ritz[i]) < eps34 * fabs(ritz[i]))
1279 0 0         if (bnd[i] > tol && bnd[i-1] > tol) {
    0          
1280 0           bnd[i-1] = sqrt(bnd[i] * bnd[i] + bnd[i-1] * bnd[i-1]);
1281 0           bnd[i] = 0.0;
1282             }
1283            
1284            
1285 10 50         for (i=((step+1) - (step-1)) / 2; i <= mid - 1; i +=1 )
1286 0 0         if (fabs(ritz[i+1] - ritz[i]) < eps34 * fabs(ritz[i]))
1287 0 0         if (bnd[i] > tol && bnd[i+1] > tol) {
    0          
1288 0           bnd[i+1] = sqrt(bnd[i] * bnd[i] + bnd[i+1] * bnd[i+1]);
1289 0           bnd[i] = 0.0;
1290             }
1291            
1292             /* refine the error bounds */
1293 10           neig = 0;
1294 10           gapl = ritz[step] - ritz[0];
1295 70 100         for (i = 0; i <= step; i++) {
1296 60           gap = gapl;
1297 60 100         if (i < step) gapl = ritz[i+1] - ritz[i];
1298 60           gap = svd_dmin(gap, gapl);
1299 60 50         if (gap > bnd[i]) bnd[i] = bnd[i] * (bnd[i] / gap);
1300 60 50         if (bnd[i] <= 16.0 * eps * fabs(ritz[i])) {
1301 60           neig++;
1302 60 50         if (!*enough) *enough = endl < ritz[i] && ritz[i] < endr;
    50          
    50          
1303             }
1304             }
1305 10           return neig;
1306             }
1307              
1308             /***********************************************************************
1309             * *
1310             * imtqlb() *
1311             * *
1312             ***********************************************************************/
1313             /***********************************************************************
1314              
1315             Description
1316             -----------
1317              
1318             imtqlb() is a translation of a Fortran version of the Algol
1319             procedure IMTQL1, Num. Math. 12, 377-383(1968) by Martin and
1320             Wilkinson, as modified in Num. Math. 15, 450(1970) by Dubrulle.
1321             Handbook for Auto. Comp., vol.II-Linear Algebra, 241-248(1971).
1322             See also B. T. Smith et al, Eispack Guide, Lecture Notes in
1323             Computer Science, Springer-Verlag, (1976).
1324              
1325             The function finds the eigenvalues of a symmetric tridiagonal
1326             matrix by the implicit QL method.
1327              
1328              
1329             Arguments
1330             ---------
1331              
1332             (input)
1333             n order of the symmetric tridiagonal matrix
1334             d contains the diagonal elements of the input matrix
1335             e contains the subdiagonal elements of the input matrix in its
1336             last n-1 positions. e[0] is arbitrary
1337              
1338             (output)
1339             d contains the eigenvalues in ascending order. if an error
1340             exit is made, the eigenvalues are correct and ordered for
1341             indices 0,1,...ierr, but may not be the smallest eigenvalues.
1342             e has been destroyed.
1343             ierr set to zero for normal return, j if the j-th eigenvalue has
1344             not been determined after 30 iterations.
1345              
1346             Functions used
1347             --------------
1348              
1349             UTILITY svd_fsign
1350             MISC svd_pythag
1351              
1352             ***********************************************************************/
1353              
1354 10           void imtqlb(__SVDLIBC_LONG n, double d[], double e[], double bnd[])
1355              
1356             {
1357             __SVDLIBC_LONG last, l, m, i, iteration;
1358              
1359             /* various flags */
1360             __SVDLIBC_LONG exchange, convergence, underflow;
1361              
1362             double b, test, g, r, s, c, p, f;
1363              
1364 10 50         if (n == 1) return;
1365 10           ierr = 0;
1366 10           bnd[0] = 1.0;
1367 10           last = n - 1;
1368 60 100         for (i = 1; i < n; i++) {
1369 50           bnd[i] = 0.0;
1370 50           e[i-1] = e[i];
1371             }
1372 10           e[last] = 0.0;
1373 70 100         for (l = 0; l < n; l++) {
1374 60           iteration = 0;
1375 210 100         while (iteration <= 30) {
1376 460 50         for (m = l; m < n; m++) {
1377 460           convergence = FALSE;
1378 460 100         if (m == last) break;
1379             else {
1380 360           test = fabs(d[m]) + fabs(d[m+1]);
1381 360 100         if (test + fabs(e[m]) == test) convergence = TRUE;
1382             }
1383 360 100         if (convergence) break;
1384             }
1385 150           p = d[l];
1386 150           f = bnd[l];
1387 150 100         if (m != l) {
1388 90 50         if (iteration == 30) {
1389 0           ierr = l;
1390 0           return;
1391             }
1392 90           iteration += 1;
1393             /*........ form shift ........*/
1394 90           g = (d[l+1] - p) / (2.0 * e[l]);
1395 90           r = svd_pythag(g, 1.0);
1396 90           g = d[m] - p + e[l] / (g + svd_fsign(r, g));
1397 90           s = 1.0;
1398 90           c = 1.0;
1399 90           p = 0.0;
1400 90           underflow = FALSE;
1401 90           i = m - 1;
1402 400 50         while (underflow == FALSE && i >= l) {
    100          
1403 310           f = s * e[i];
1404 310           b = c * e[i];
1405 310           r = svd_pythag(f, g);
1406 310           e[i+1] = r;
1407 310 50         if (r == 0.0) underflow = TRUE;
1408             else {
1409 310           s = f / r;
1410 310           c = g / r;
1411 310           g = d[i+1] - p;
1412 310           r = (d[i] - g) * s + 2.0 * c * b;
1413 310           p = s * r;
1414 310           d[i+1] = g + p;
1415 310           g = c * r - b;
1416 310           f = bnd[i+1];
1417 310           bnd[i+1] = s * bnd[i] + c * f;
1418 310           bnd[i] = c * bnd[i] - s * f;
1419 310           i--;
1420             }
1421             } /* end while (underflow != FALSE && i >= l) */
1422             /*........ recover from underflow .........*/
1423 90 50         if (underflow) {
1424 0           d[i+1] -= p;
1425 0           e[m] = 0.0;
1426             }
1427             else {
1428 90           d[l] -= p;
1429 90           e[l] = g;
1430 90           e[m] = 0.0;
1431             }
1432             } /* end if (m != l) */
1433             else {
1434              
1435             /* order the eigenvalues */
1436 60           exchange = TRUE;
1437 60 100         if (l != 0) {
1438 50           i = l;
1439 110 50         while (i >= 1 && exchange == TRUE) {
    100          
1440 60 100         if (p < d[i-1]) {
1441 10           d[i] = d[i-1];
1442 10           bnd[i] = bnd[i-1];
1443 10           i--;
1444             }
1445 50           else exchange = FALSE;
1446             }
1447             }
1448 60 100         if (exchange) i = 0;
1449 60           d[i] = p;
1450 60           bnd[i] = f;
1451 60           iteration = 31;
1452             }
1453             } /* end while (iteration <= 30) */
1454             } /* end for (l=0; l
1455 10           return;
1456             } /* end main */
1457              
1458             /***********************************************************************
1459             * *
1460             * imtql2() *
1461             * *
1462             ***********************************************************************/
1463             /***********************************************************************
1464              
1465             Description
1466             -----------
1467              
1468             imtql2() is a translation of a Fortran version of the Algol
1469             procedure IMTQL2, Num. Math. 12, 377-383(1968) by Martin and
1470             Wilkinson, as modified in Num. Math. 15, 450(1970) by Dubrulle.
1471             Handbook for Auto. Comp., vol.II-Linear Algebra, 241-248(1971).
1472             See also B. T. Smith et al, Eispack Guide, Lecture Notes in
1473             Computer Science, Springer-Verlag, (1976).
1474              
1475             This function finds the eigenvalues and eigenvectors of a symmetric
1476             tridiagonal matrix by the implicit QL method.
1477              
1478              
1479             Arguments
1480             ---------
1481              
1482             (input)
1483             nm row dimension of the symmetric tridiagonal matrix
1484             n order of the matrix
1485             d contains the diagonal elements of the input matrix
1486             e contains the subdiagonal elements of the input matrix in its
1487             last n-1 positions. e[0] is arbitrary
1488             z contains the identity matrix
1489            
1490             (output)
1491             d contains the eigenvalues in ascending order. if an error
1492             exit is made, the eigenvalues are correct but unordered for
1493             for indices 0,1,...,ierr.
1494             e has been destroyed.
1495             z contains orthonormal eigenvectors of the symmetric
1496             tridiagonal (or full) matrix. if an error exit is made,
1497             z contains the eigenvectors associated with the stored
1498             eigenvalues.
1499             ierr set to zero for normal return, j if the j-th eigenvalue has
1500             not been determined after 30 iterations.
1501              
1502              
1503             Functions used
1504             --------------
1505             UTILITY svd_fsign
1506             MISC svd_pythag
1507              
1508             ***********************************************************************/
1509              
1510 10           void imtql2(__SVDLIBC_LONG nm, __SVDLIBC_LONG n, double d[], double e[], double z[])
1511              
1512             {
1513             __SVDLIBC_LONG index, nnm, j, last, l, m, i, k, iteration, convergence, underflow;
1514             double b, test, g, r, s, c, p, f;
1515 10 50         if (n == 1) return;
1516 10           ierr = 0;
1517 10           last = n - 1;
1518 60 100         for (i = 1; i < n; i++) e[i-1] = e[i];
1519 10           e[last] = 0.0;
1520 10           nnm = n * nm;
1521 70 100         for (l = 0; l < n; l++) {
1522 60           iteration = 0;
1523              
1524             /* look for small sub-diagonal element */
1525 150 50         while (iteration <= 30) {
1526 460 50         for (m = l; m < n; m++) {
1527 460           convergence = FALSE;
1528 460 100         if (m == last) break;
1529             else {
1530 360           test = fabs(d[m]) + fabs(d[m+1]);
1531 360 100         if (test + fabs(e[m]) == test) convergence = TRUE;
1532             }
1533 360 100         if (convergence) break;
1534             }
1535 150 100         if (m != l) {
1536              
1537             /* set error -- no convergence to an eigenvalue after
1538             * 30 iterations. */
1539 90 50         if (iteration == 30) {
1540 0           ierr = l;
1541 0           return;
1542             }
1543 90           p = d[l];
1544 90           iteration += 1;
1545              
1546             /* form shift */
1547 90           g = (d[l+1] - p) / (2.0 * e[l]);
1548 90           r = svd_pythag(g, 1.0);
1549 90           g = d[m] - p + e[l] / (g + svd_fsign(r, g));
1550 90           s = 1.0;
1551 90           c = 1.0;
1552 90           p = 0.0;
1553 90           underflow = FALSE;
1554 90           i = m - 1;
1555 400 50         while (underflow == FALSE && i >= l) {
    100          
1556 310           f = s * e[i];
1557 310           b = c * e[i];
1558 310           r = svd_pythag(f, g);
1559 310           e[i+1] = r;
1560 310 50         if (r == 0.0) underflow = TRUE;
1561             else {
1562 310           s = f / r;
1563 310           c = g / r;
1564 310           g = d[i+1] - p;
1565 310           r = (d[i] - g) * s + 2.0 * c * b;
1566 310           p = s * r;
1567 310           d[i+1] = g + p;
1568 310           g = c * r - b;
1569              
1570             /* form vector */
1571 2170 100         for (k = 0; k < nnm; k += n) {
1572 1860           index = k + i;
1573 1860           f = z[index+1];
1574 1860           z[index+1] = s * z[index] + c * f;
1575 1860           z[index] = c * z[index] - s * f;
1576             }
1577 310           i--;
1578             }
1579             } /* end while (underflow != FALSE && i >= l) */
1580             /*........ recover from underflow .........*/
1581 90 50         if (underflow) {
1582 0           d[i+1] -= p;
1583 0           e[m] = 0.0;
1584             }
1585             else {
1586 90           d[l] -= p;
1587 90           e[l] = g;
1588 90           e[m] = 0.0;
1589             }
1590             }
1591 60           else break;
1592             } /*...... end while (iteration <= 30) .........*/
1593             } /*...... end for (l=0; l
1594              
1595             /* order the eigenvalues */
1596 60 100         for (l = 1; l < n; l++) {
1597 50           i = l - 1;
1598 50           k = i;
1599 50           p = d[i];
1600 200 100         for (j = l; j < n; j++) {
1601 150 100         if (d[j] < p) {
1602 10           k = j;
1603 10           p = d[j];
1604             }
1605             }
1606             /* ...and corresponding eigenvectors */
1607 50 100         if (k != i) {
1608 10           d[k] = d[i];
1609 10           d[i] = p;
1610 70 100         for (j = 0; j < nnm; j += n) {
1611 60           p = z[j+i];
1612 60           z[j+i] = z[j+k];
1613 60           z[j+k] = p;
1614             }
1615             }
1616             }
1617 10           return;
1618             } /*...... end main ............................*/
1619              
1620             /***********************************************************************
1621             * *
1622             * machar() *
1623             * *
1624             ***********************************************************************/
1625             /***********************************************************************
1626              
1627             Description
1628             -----------
1629              
1630             This function is a partial translation of a Fortran-77 subroutine
1631             written by W. J. Cody of Argonne National Laboratory.
1632             It dynamically determines the listed machine parameters of the
1633             floating-point arithmetic. According to the documentation of
1634             the Fortran code, "the determination of the first three uses an
1635             extension of an algorithm due to M. Malcolm, ACM 15 (1972),
1636             pp. 949-951, incorporating some, but not all, of the improvements
1637             suggested by M. Gentleman and S. Marovich, CACM 17 (1974),
1638             pp. 276-277." The complete Fortran version of this translation is
1639             documented in W. J. Cody, "Machar: a Subroutine to Dynamically
1640             Determine Determine Machine Parameters," TOMS 14, December, 1988.
1641              
1642              
1643             Parameters reported
1644             -------------------
1645              
1646             ibeta the radix for the floating-point representation
1647             it the number of base ibeta digits in the floating-point
1648             significand
1649             irnd 0 if floating-point addition chops
1650             1 if floating-point addition rounds, but not in the
1651             ieee style
1652             2 if floating-point addition rounds in the ieee style
1653             3 if floating-point addition chops, and there is
1654             partial underflow
1655             4 if floating-point addition rounds, but not in the
1656             ieee style, and there is partial underflow
1657             5 if floating-point addition rounds in the ieee style,
1658             and there is partial underflow
1659             machep the largest negative integer such that
1660             1.0+float(ibeta)**machep .ne. 1.0, except that
1661             machep is bounded below by -(it+3)
1662             negeps the largest negative integer such that
1663             1.0-float(ibeta)**negeps .ne. 1.0, except that
1664             negeps is bounded below by -(it+3)
1665              
1666             ***********************************************************************/
1667              
1668 10           void machar(__SVDLIBC_LONG *ibeta, __SVDLIBC_LONG *it, __SVDLIBC_LONG *irnd, __SVDLIBC_LONG *machep, __SVDLIBC_LONG *negep) {
1669              
1670             volatile double beta, betain, betah, a, b, ZERO, ONE, TWO, temp, tempa,
1671             temp1;
1672             __SVDLIBC_LONG i, itemp;
1673            
1674 10           ONE = (double) 1;
1675 10           TWO = ONE + ONE;
1676 10           ZERO = ONE - ONE;
1677            
1678 10           a = ONE;
1679 10           temp1 = ONE;
1680 540 100         while (temp1 - ONE == ZERO) {
1681 530           a = a + a;
1682 530           temp = a + ONE;
1683 530           temp1 = temp - a;
1684 530           b += a; /* to prevent icc compiler error */
1685             }
1686 10           b = ONE;
1687 10           itemp = 0;
1688 20 100         while (itemp == 0) {
1689 10           b = b + b;
1690 10           temp = a + b;
1691 10           itemp = (__SVDLIBC_LONG)(temp - a);
1692             }
1693 10           *ibeta = itemp;
1694 10           beta = (double) *ibeta;
1695            
1696 10           *it = 0;
1697 10           b = ONE;
1698 10           temp1 = ONE;
1699 540 100         while (temp1 - ONE == ZERO) {
1700 530           *it = *it + 1;
1701 530           b = b * beta;
1702 530           temp = b + ONE;
1703 530           temp1 = temp - b;
1704             }
1705 10           *irnd = 0;
1706 10           betah = beta / TWO;
1707 10           temp = a + betah;
1708 10 50         if (temp - a != ZERO) *irnd = 1;
1709 10           tempa = a + beta;
1710 10           temp = tempa + betah;
1711 10 50         if ((*irnd == 0) && (temp - tempa != ZERO)) *irnd = 2;
    50          
1712            
1713 10           *negep = *it + 3;
1714 10           betain = ONE / beta;
1715 10           a = ONE;
1716 570 100         for (i = 0; i < *negep; i++) a = a * betain;
1717 10           b = a;
1718 10           temp = ONE - a;
1719 40 100         while (temp-ONE == ZERO) {
1720 30           a = a * beta;
1721 30           *negep = *negep - 1;
1722 30           temp = ONE - a;
1723             }
1724 10           *negep = -(*negep);
1725            
1726 10           *machep = -(*it) - 3;
1727 10           a = b;
1728 10           temp = ONE + a;
1729 50 100         while (temp - ONE == ZERO) {
1730 40           a = a * beta;
1731 40           *machep = *machep + 1;
1732 40           temp = ONE + a;
1733             }
1734 10           eps = a;
1735 10           return;
1736             }
1737              
1738             /***********************************************************************
1739             * *
1740             * store() *
1741             * *
1742             ***********************************************************************/
1743             /***********************************************************************
1744              
1745             Description
1746             -----------
1747              
1748             store() is a user-supplied function which, based on the input
1749             operation flag, stores to or retrieves from memory a vector.
1750              
1751              
1752             Arguments
1753             ---------
1754              
1755             (input)
1756             n length of vector to be stored or retrieved
1757             isw operation flag:
1758             isw = 1 request to store j-th Lanczos vector q(j)
1759             isw = 2 request to retrieve j-th Lanczos vector q(j)
1760             isw = 3 request to store q(j) for j = 0 or 1
1761             isw = 4 request to retrieve q(j) for j = 0 or 1
1762             s contains the vector to be stored for a "store" request
1763              
1764             (output)
1765             s contains the vector retrieved for a "retrieve" request
1766              
1767             Functions used
1768             --------------
1769              
1770             BLAS svd_dcopy
1771              
1772             ***********************************************************************/
1773              
1774 440           void store(__SVDLIBC_LONG n, __SVDLIBC_LONG isw, __SVDLIBC_LONG j, double *s) {
1775             /* printf("called store %ld %ld\n", isw, j); */
1776 440           switch(isw) {
1777             case STORQ:
1778 60 50         if (!LanStore[j + MAXLL]) {
1779 60 50         if (!(LanStore[j + MAXLL] = svd_doubleArray(n, FALSE, "LanStore[j]")))
1780 0           svd_fatalError("svdLAS2: failed to allocate LanStore[%d]", j + MAXLL);
1781             }
1782 60           svd_dcopy(n, s, 1, LanStore[j + MAXLL], 1);
1783 60           break;
1784             case RETRQ:
1785 360 50         if (!LanStore[j + MAXLL])
1786 0           svd_fatalError("svdLAS2: store (RETRQ) called on index %d (not allocated)",
1787             j + MAXLL);
1788 360           svd_dcopy(n, LanStore[j + MAXLL], 1, s, 1);
1789 360           break;
1790             case STORP:
1791 20 50         if (j >= MAXLL) {
1792 0           svd_error("svdLAS2: store (STORP) called with j >= MAXLL");
1793 0           break;
1794             }
1795 20 50         if (!LanStore[j]) {
1796 20 50         if (!(LanStore[j] = svd_doubleArray(n, FALSE, "LanStore[j]")))
1797 0           svd_fatalError("svdLAS2: failed to allocate LanStore[%d]", j);
1798             }
1799 20           svd_dcopy(n, s, 1, LanStore[j], 1);
1800 20           break;
1801             case RETRP:
1802 0 0         if (j >= MAXLL) {
1803 0           svd_error("svdLAS2: store (RETRP) called with j >= MAXLL");
1804 0           break;
1805             }
1806 0 0         if (!LanStore[j])
1807 0           svd_fatalError("svdLAS2: store (RETRP) called on index %d (not allocated)",
1808             j);
1809 0           svd_dcopy(n, LanStore[j], 1, s, 1);
1810 0           break;
1811             }
1812 440           return;
1813             }