📄 las1.c
字号:
/************************************************************************* (c) Copyright 1993 University of Tennessee All Rights Reserved *************************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <math.h>#include <fcntl.h>#include "las1.h"#define UNIX_CREAT#ifdef UNIX_CREAT#define PERMS 0664#endifint landr(int, int, int, int, float, float, int, float, float *, float *, float *);void dscal(int, float, float *,int);void daxpy(int, float, float *,int, float *, int);float ddot(int, float *,int, float *, int);void opb(int, float *, float *);void write_data(int, int, float, float, int, float, char *,char *, int, int, int);int check_parameters(int, int, int, float, float, int, int); float timer(void);/*********************************************************************** * * * main() * * Sparse SVD Via Eigensystem of Equivalent 2-Cyclic Matrix * * (float precision) * * * ***********************************************************************//*********************************************************************** Description ----------- This sample program uses landr to compute singular triplets of A via the equivalent symmetric eigenvalue problem B x = lambda x, where x' = (u',v'), lambda = +/- sigma, where sigma is a singular value of A, [o A] B = [ ] , and A is m (nrow) by n (ncol) (nrow >> ncol), [A' o] so that {u, abs(lambda), v} is a singular triplet of A. (A' = transpose of A) User supplied routines: opb, store, timer opb(nrow+ncol,x,y) takes an (m+n)-vector x and returns B*x in y. Based on operation flag isw, store(n,isw,j,s) stores/retrieves to/from storage a vector of length n in s. User should edit timer() with an appropriate call to an intrinsic timing routine that returns elapsed user cpu time. External parameters ------------------- Defined and documented in las1.h Local parameters ---------------- (input) endl left end of interval containing unwanted eigenvalues of B endr right end of interval containing unwanted eigenvalues of B kappa relative accuracy of ritz values acceptable as eigenvalues of B r work array n dimension of the eigenproblem for matrix B (nrow + ncol) maxprs upper limit of desired number of singular triplets of A lanmax upper limit of desired number of Lanczos steps nnzero number of nonzeros in A vectors 1 indicates both singular values and singular vectors are wanted and they can be found in output file lav1; 0 indicates only singular values are wanted (output) ritz array of ritz values bnd array of error bounds d array of singular values memory total memory allocated in bytes to solve B-eigenproblem Functions used -------------- BLAS daxpy, dscal, ddot USER opb, timer MISC write_data, check_parameters LAS1 landr Precision --------- All floating-point calculations use float precision; variables are declared as int and float. LAS1 development ---------------- LAS1 is a C translation of the Fortran-77 LAS1 from the SVDPACK library written by Michael W. Berry, University of Tennessee, Dept. of Computer Science, 107 Ayres Hall, Knoxville, TN, 37996-1301 31 Jan 1992: Date written Theresa H. Do University of Tennessee Dept. of Computer Science 107 Ayres Hall Knoxville, TN, 37996-1301 internet: tdo@cs.utk.edu ***********************************************************************/main() { float t0, exetime; float endl, endr, kappa, tmp0, tmp1, tmp2, tmp3, xnorm; float *r, *ritz, *bnd, *d, *tptr1; int k, i, id, n, lanmax, maxprs, nnzero, size1, size2, memory, vectors; int *tptr3, hcount; char title[73], name[41], v[6]; char *in1, *in2, *out1, *out2; FILE *fp_in1, *fp_in2; in1 = "lap1"; in2 = "matrix"; out1 = "lao1"; out2 = "lav1"; /* open files for input/output */ if (!(fp_in1 = fopen(in1, "r"))) { printf("cannot open file %s for reading\n", in1); exit(-1); } if (!(fp_in2 = fopen(in2, "r"))) { printf("cannot open file %s for reading\n", in2); exit(-1); } if (!(fp_out1 = fopen(out1, "w"))) { printf("cannot open output file %s \n", out1); exit(-1); } /* read data */ fscanf (fp_in2,"%72c%*s%*s%*s%d%d%d%*d", title, &nrow, &ncol, &nnzero); title[73] = '\0'; fscanf (fp_in1,"%s %d %d %f %f %s %f", name, &lanmax, &maxprs, &endl, &endr, v, &kappa); if (!(strcmp(v, "TRUE"))) { vectors = 1;#if !defined UNIX_CREAT if ((fp_out2 = open(out2, O_CREAT | O_RDWR)) == -1) { printf("cannot open output file %s \n", out2); exit(-1); }#else if ((fp_out2 = creat(out2, PERMS )) == -1) { printf("cannot open output file %s \n", out2); exit(-1); }#endif } else vectors = 0; n = nrow + ncol; /* write header of output file */ write_data(lanmax, maxprs, endl, endr, vectors, kappa, title, name, nrow, ncol, n); /* even though the validity of the parameters will be checked in the * SVD code, some parameter checking should also be done before * allocating memory to ensure that they are nonnegative */ if (check_parameters(maxprs, lanmax, n, endl, endr, vectors, nnzero)) { fclose(fp_in1); fclose(fp_in2); fclose(fp_out1); if (vectors) close(fp_out2); exit(-1); } /******************************************************************* * allocate memory * * pointr - column start array of harwell-boeing sparse matrix * * format (ncol+1) * * rowind - row indices array of harwell-boeing format (nnzero) * * value - nonzero values array of harwell-boeing sparse matrix * * format (nnzero) * * r - work array (n) * * ritz - array of ritz values (n) * * bnd - array of error bounds (n) * * d - array of approximate singular values of matrix A (n) * * a - storage area for Lanczos vectors (n * (lanmax+2)) * *******************************************************************/ size1 = sizeof(float) * (n * (lanmax + 6) + nnzero); size2 = sizeof(int) * (ncol + nnzero + 1); if (!(pointr = (int *) malloc(size2)) || !(value = (float *) malloc(size1))){ perror("MALLOC FAILED in MAIN()"); exit(errno); } tptr1 = value; /* calculate memory allocated for problem (including work space in landr */ memory = size1 + size2 + sizeof(float) * (5 * n + 4 * lanmax + 1); rowind = pointr + (ncol + 1); tptr1 += nnzero; r = tptr1; tptr1 += n; ritz = tptr1; tptr1 += n; bnd = tptr1; tptr1 += n; d = tptr1; tptr1 += n; a = tptr1; /* skip data format line */ fscanf(fp_in2,"%*s %*s %*s %*s"); /* read data */ for (i = 0; i <= ncol; i++) fscanf(fp_in2, "%d", &pointr[i]); for (i = 0; i < ncol; i++) pointr[i] -= 1; /* define last element of pointr in case it is not */ pointr[i] = nnzero; for (i = 0; i < nnzero; i++) fscanf(fp_in2, "%d", &rowind[i]); for (i = 0; i < nnzero; i++) rowind[i] -= 1; for (i = 0; i < nnzero; i++) fscanf(fp_in2, "%f", &value[i]); /* to get a random starting vector, the first n cells must be * initialize to zero */ for (i = 0; i < n; i++) r[i] = 0.; exetime = timer(); /* make a lanczos run; exit upon error */ if(landr(n, lanmax, maxprs, nnzero, endl, endr, vectors, kappa, ritz, bnd, r)){ free(value); free(pointr); fclose(fp_in1); fclose(fp_in2); fclose(fp_out1); if (vectors){ close(fp_out2); free(xv1); free(xv2); } exit(-1); } exetime = timer() - exetime; /* calculating singular vectors requires extra work space * (xv1, xv2, s) in landr() */ if (vectors) memory += sizeof(float) * (n*(j+1) + n + (j+1)*(j+1)); /* print error code if not zero */ if (ierr)fprintf(fp_out1," ... RETURN FLAG = %9d ...\n",ierr); /* ...Print ritz values and error bounds */ fprintf(fp_out1,"\n"); fprintf(fp_out1," ...... ALLOCATED MEMORY (BYTES)= %10.2E\n",(float)memory); fprintf(fp_out1," ...... LANSO EXECUTION TIME=%10.2E\n",exetime); fprintf(fp_out1," ...... \n"); fprintf(fp_out1," ...... NUMBER OF LANCZOS STEPS = %3d NEIG = %3d\n",j+1,neig); fprintf(fp_out1," ...... \n"); fprintf(fp_out1," ...... COMPUTED RITZ VALUES (ERROR BNDS)\n"); fprintf(fp_out1," ...... \n"); for (i = 0; i <= j; i++) fprintf(fp_out1," ...... %3d %22.14E (%11.2E)\n",i+1,ritz[i],bnd[i]); /* compute residual error when singular values and vectors are * computed */ if (vectors) { t0 = timer(); id = 0; for (i = 0; i < nsig; i++) { /* multiply by 2-cyclic indefinite matrix */ opb(n, &xv1[id], xv2); tmp0 = ddot(n, &xv1[id], 1, xv2, 1); tmp1 = ddot(nrow, &xv1[id], 1, &xv1[id], 1); tmp2 = ddot(ncol, &xv1[id + nrow], 1, &xv1[id + nrow], 1); tmp3 = sqrt(tmp1 + tmp2); daxpy(n, -tmp0, &xv1[id], 1, xv2, 1); xnorm = ddot(n, xv2, 1, xv2, 1); xnorm = sqrt(xnorm); bnd[i] = xnorm / tmp3; d[i] = fabs(tmp0); id += n; } exetime += (timer() - t0); hcount=mxvcount/2; fprintf(fp_out1," ...... \n"); fprintf(fp_out1," ...... NO. MULTIPLICATIONS BY A =%10d\n", hcount); fprintf(fp_out1," ...... NO. MULT. BY TRANSPOSE(A) =%10d\n", hcount); fprintf(fp_out1,"\n"); fprintf(fp_out1," ...... LASVD EXECUTION TIME=%10.2E\n",exetime); fprintf(fp_out1," ...... \n"); fprintf(fp_out1," ...... NSIG = %4d\n", nsig); fprintf(fp_out1," ...... \n"); fprintf(fp_out1," ...... COMPUTED S-VALUES (RES. NORMS)\n"); fprintf(fp_out1," ...... \n"); for (i = 0; i < nsig; i++) fprintf(fp_out1," ...... %3d %22.14E (%11.2E)\n", i + 1, d[i], bnd[i]); } else { for (i = j; i >= 0; i--) if (bnd[i] > kappa * fabs(ritz[i])) break; nsig = j - i; hcount=mxvcount/2; fprintf(fp_out1," ...... \n"); fprintf(fp_out1," ...... NO. MULTIPLICATIONS BY A =%10d\n", hcount); fprintf(fp_out1," ...... NO. MULT. BY TRANSPOSE(A) =%10d\n", hcount); fprintf(fp_out1,"\n"); fprintf(fp_out1," ...... LASVD EXECUTION TIME=%10.2E\n", exetime); fprintf(fp_out1," ...... \n"); fprintf(fp_out1," ...... NSIG = %4d\n", nsig); fprintf(fp_out1," ...... \n"); fprintf(fp_out1," ...... COMPUTED S-VALUES (ERROR BNDS)\n"); fprintf(fp_out1," ...... \n"); k = j + 1 - nsig; for (i = 1 ; i <= nsig; i++) { fprintf(fp_out1," ...... %3d %22.14E (%11.2E)\n", i, ritz[k], bnd[k]); k++; } } free(value); free(pointr); fclose(fp_in1); fclose(fp_in2); fclose(fp_out1); if (vectors) { free(xv1); free(xv2); close(fp_out2); } exit(0);}extern int ncol,nrow;extern char *error[];extern FILE *fp_out1;/*********************************************************************** * * * check_parameters() * * * ***********************************************************************//*********************************************************************** Description ----------- Function validates input parameters and returns error code (int) Parameters ---------- (input) maxprs upper limit of desired number of eigenpairs of B lanmax upper limit of desired number of lanczos steps n dimension of the eigenproblem for matrix B endl left end of interval containing unwanted eigenvalues of B endr right end of interval containing unwanted eigenvalues of B vectors 1 indicates both eigenvalues and eigenvectors are wanted and they can be found in lav1; 0 indicates eigenvalues only nnzero number of nonzero elements in input matrix (matrix A) ***********************************************************************/int check_parameters(int maxprs, int lanmax, int n, float endl, float endr, int vectors, int nnzero) { int error_index, ncells; error_index = 0; /* assuming that nrow >= ncol... */ if (ncol >= NMAX || nnzero > NZMAX) error_index = 1; else if (endl >= endr) error_index = 2; else if (maxprs > lanmax) error_index = 3; else if (n <= 0) error_index = 4; else if (lanmax <= 0 || lanmax > n) error_index = 5; else if (maxprs <= 0 || maxprs > lanmax) error_index = 6; else { if (vectors) { ncells = 6 * n + 4 * lanmax + 1 + lanmax * lanmax; if (ncells > LMTNW) error_index = 7; } else { ncells = 6 * n + 4 * lanmax + 1; if (ncells > LMTNW) error_index = 8; } } if (error_index) fprintf(fp_out1, "%s\n", error[error_index]); return(error_index);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -