int LinearFitting::computeFitting(double *fitting, double *model, int nModel, int index1, int index2, double &xAtMin) //The model is represented by an array of real numbers that are the //exponentials. For example, if model={0, 0.5, 1.0, 2.0}, then, //nModel would be 4; and y=c_0*x^0 + c_1*x^0.5 + c_2*x + c_3*x^2.0 . //index1 and index2 are the starting index and endind index of the //fitting range. { if( index1>index2 || index1<0 || index2>(nDim-1) ) return 1; int M=index2-index1+1; int N=nModel; int i, j; double lastMin, xx, val; double inc=1.0/(nDim-1); double *a=(double *)malloc(N*M*sizeof(double)); double *aa=(double *)malloc(N*nDim*sizeof(double)); for( i=0; i<N; i++){ for(j=0; j<M; j++){ *(a+i*M+j)=pow( (index1+j)*inc, model[i] ); } } for( i=0; i<N; i++) for(j=0; j<nDim; j++){ *(aa+i*nDim+j)=pow( j*inc, model[i] ); } double *b=(double *)malloc(M*sizeof(double)); for(i=0;i<M;i++) { b[i]=raw[i+index1]; } for(i=0;i<nDim;i++) fitting[i]=0.0; int NRHS=1; int LWORK=5*M*N; double *work=(double*)malloc(LWORK*sizeof(double)); /* = 0: successful exit * < 0: if INFO = -i, the i-th argument had an illegal value. * > 0: the algorithm for computing the SVD failed to converge; * if INFO = i, i off-diagonal elements of an intermediate * bidiagonal form did not converge to zero. */ int INFO=1000; double *sv=(double*)malloc(N*sizeof(double)); // store singular values //negative: so machine precision is used as minimun singular value; double RCOND=-5.0; int RANK=-3; //Solve the minimum norm problem || b- A^T * X ||, //M is the number of rows of A^T, the solution is stored in b. dgelss(&M, &N, &NRHS, a, &M, b, &M, sv, &RCOND, &RANK, work, &LWORK, &INFO); for(i=0;i<nDim;i++) for(j=0;j<N;j++) fitting[i]+=b[j]*(*(aa+j*nDim+i)); printf("Linear fitting parameters for range %d to %d are:\n", index1, index2); for(i=0;i<N;i++) printf("x[%d]=%f\t", i, b[i]); printf("RANK=%d INFO=%d \n", RANK, INFO); // Find the first minimum after the starting point xAtMin = index1 * inc; lastMin = fitting[index1]; for (i = 0; i < (index2 + 1 - index1) * 10000; i++) { xx = (index1 + (i + 1) / 10000.) * inc; val = 0.; for(j=0;j<N;j++) val += b[j] * pow(xx, model[j]); if (val > lastMin) break; xAtMin = xx; lastMin = val; } free(a); free(aa); free(b); free(work); free(sv); return INFO; }
END_TEST START_TEST( using_MKL_SVD ) { PetscErrorCode ierr; int Np = 7; int m = Np, n = 3; int lda = m; double *a; PetscMalloc(m*n*sizeof(double), &a); double aa[21] = {1., -2.50725, 6.28632, 1., -1.7072, 2.91453, 1., -0.726423, 0.527691, 1., \ 0.452286, 0.204562, 1., 1.81034, 3.27735, 1., 2.53149, 6.40844, 1., 3.76245, \ 14.1561}; double at[21] = {1, 1, 1, 1, 1, 1, 1, -2.50725, -1.7072, -0.726423, 0.452286, 1.81034, \ 2.53149, 3.76245, 3.14316, 1.45727, 0.263846, 0.102281, 1.63868, 3.20422, \ 7.07805}; double y[7]={1, 2, 5, 9, 7, 6, 5}; for( int i = 0; i < m*n; i++ ) a[i] = at[i]; int ldb = Np; int nrhs = 1; double *b; PetscMalloc(Np*nrhs*sizeof(double), &b); PetscMemzero(b,Np*nrhs*sizeof(double)); // double bb[9] = {one, zero, zero, // zero, one, zero, // zero, zero, one}; // for( int i = 0; i < nrhs*m; i++) // b[i] = bb[i]; /* NEED B matrix to be Np identity!!! */ for( int i = 0; i < Np*nrhs; i++) b[i] = y[i]; // b[i+i*Np] = one; double rcond = -1; int lwork = 1000; double *work; PetscMalloc(lwork*sizeof(double), &work); // PetscMemzero(work, lwork*sizeof(double)); int rank; double *s; PetscMalloc( m*sizeof(double), &s); int info; dgelss( &m /* num rows in A */, //3 &n /* num cols in A */, //7 &nrhs /* num cols in B */,//3 a /* matrix A for SVD */, &lda /* first dim of A = max( 1, m )*/, //3 b /* matrix B of RHS (become solution matrix x) */, &ldb /* first dim of B = max( 1, m, n ) */, //7 s /* matrix of s.v */, &rcond /* relative condition s.v. treated as zero */, //-1 &rank /* */, work /* */, &lwork /* size of work */, &info /* */ ); printf("rank: %d\n", rank); printf("work[0]: %f\n", work[0] ); printf("info: %d\n", info); for( int i = 0; i < n+0*Np*nrhs; i++) printf("b %d: %f\n", i, b[i]); printf("\n"); for( int i = 0; i < 3; i++) printf("s %d: %f\n", i, s[i]); printf("\n"); for( int i = 0; i < m*n; i++) printf("a %d: %f\n", i, a[i]); printf("\n"); }