#include #include #include #include #include #include "sysdep.h" #include "linear.h" #include "output.h" #include "mainloop.h" #include "interval.h" char *ram; static int *perm,*col,signdet,luflag=0; static double **lumat,*c,det; static complex **c_lumat,*c_c,c_det; static int rank; static long nmark; #define superalign(n) ((((n)-1)/ALIGNMENT+1)*ALIGNMENT) #define increase(r,n) nmark=superalign(n); if (!freeramfrom((r),(nmark))) outofram(); (r)+=nmark; /***************** real linear systems *******************/ static void lu (double *a, int n, int m) /***** lu lu decomposition of a *****/ { int i,j,k,mm,j0,kh,j1; double *d,piv,temp,*temp1; if (!luflag) { /* get place for result c and move a to c */ c=(double *)ram; increase(ram,(long)n*m*sizeof(double)); memmove((char *)c,(char *)a,(long)n*m*sizeof(double)); } else c=a; /* inititalize lumat */ lumat=(double **)ram; increase(ram,(long)n*sizeof(double *)); d=c; for (i=0; i=n) { kh++; break; } } } if (k=0; k--) { for (sum=0.0, j=k+1; j=0; k--) { for (sum=0.0, j=k+1; j=n) { kh++; break; } } if (k=0; k--) { sum[0]=0; sum[1]=0.0; for (j=k+1; j=0; k--) { sum[0]=0; sum[1]=0.0; for (j=k+1; jtype==s_matrix || hd->type==s_real) { getmatrix(hd,&r,&c,&m); if (hd1->type==s_cmatrix) { make_complex(st); msolve(st); return; } if (hd1->type!=s_matrix && hd1->type!=s_real) wrong_arg_in("\\"); getmatrix(hd1,&r1,&c1,&m1); if (c!=r || c<1 || r!=r1) wrong_arg_in("\\"); result=new_matrix(r,c1,""); if (error) return; solvesim(m,r,m1,c1,matrixof(result)); if (error) return; moveresult(st,result); } else if (hd->type==s_cmatrix || hd->type==s_complex) { getmatrix(hd,&r,&c,&m); if (hd1->type==s_matrix || hd1->type==s_real) { make_complex(next_param(st)); msolve(st); return; } if (hd1->type!=s_cmatrix && hd1->type!=s_complex) wrong_arg_in("\\"); getmatrix(hd1,&r1,&c1,&m1); if (c!=r || c<1 || r!=r1) wrong_arg_in("\\"); result=new_cmatrix(r,c1,""); if (error) return; c_solvesim(m,r,m1,c1,matrixof(result)); if (error) return; moveresult(st,result); } else if (hd->type==s_imatrix || hd->type==s_interval) { getmatrix(hd,&r,&c,&m); if (hd1->type==s_matrix || hd1->type==s_real) { make_interval(next_param(st)); msolve(st); return; } if (hd1->type!=s_imatrix && hd1->type!=s_interval) wrong_arg_in("\\"); getmatrix(hd1,&r1,&c1,&m1); if (c!=r || c<1 || r!=r1) wrong_arg_in("\\"); result=new_imatrix(r,c1,""); if (error) return; i_solvesim(m,r,m1,c1,matrixof(result)); if (error) return; moveresult(st,result); } else wrong_arg_in("\\"); } void mlu (header *hd) { header *st=hd,*result,*res1,*res2,*res3; double *m,*mr,*m1,*m2,det,deti; int r,c,*rows,*cols,rank,i; hd=getvalue(hd); if (error) return; if (hd->type==s_matrix || hd->type==s_real) { getmatrix(hd,&r,&c,&m); if (r<1) wrong_arg_in("lu"); result=new_matrix(r,c,""); if (error) return; mr=matrixof(result); memmove((char *)mr,(char *)m,(long)r*c*sizeof(double)); make_lu(mr,r,c,&rows,&cols,&rank,&det); if (error) return; res1=new_matrix(1,rank,""); if (error) return; res2=new_matrix(1,c,""); if (error) return; res3=new_real(det,""); if (error) return; m1=matrixof(res1); for (i=0; itype==s_cmatrix || hd->type==s_complex) { getmatrix(hd,&r,&c,&m); if (r<1) wrong_arg_in("lu"); result=new_cmatrix(r,c,""); if (error) return; mr=matrixof(result); memmove((char *)mr,(char *)m,(long)r*c*(long)2*sizeof(double)); cmake_lu(mr,r,c,&rows,&cols,&rank,&det,&deti); if (error) return; res1=new_matrix(1,rank,""); if (error) return; res2=new_matrix(1,c,""); if (error) return; res3=new_complex(det,deti,""); if (error) return; m1=matrixof(res1); for (i=0; itype==s_matrix || hd->type==s_real) { getmatrix(hd,&r,&c,&m); if (hd1->type==s_cmatrix) { make_complex(st); mlusolve(st); return; } if (hd1->type!=s_matrix && hd1->type!=s_real) wrong_arg_in("lu"); getmatrix(hd1,&r1,&c1,&m1); if (c!=r || c<1 || r!=r1) wrong_arg_in("lu"); result=new_matrix(r,c1,""); if (error) return; lu_solve(m,r,m1,c1,matrixof(result)); if (error) return; moveresult(st,result); } else if (hd->type==s_cmatrix || hd->type==s_complex) { getmatrix(hd,&r,&c,&m); if (hd1->type==s_matrix || hd1->type==s_real) { make_complex(next_param(st)); mlusolve(st); return; } if (hd1->type!=s_cmatrix && hd1->type!=s_complex) wrong_arg_in("lu"); getmatrix(hd1,&r1,&c1,&m1); if (c!=r || c<1 || r!=r1) wrong_arg_in("lu"); result=new_cmatrix(r,c1,""); if (error) return; clu_solve(m,r,m1,c1,matrixof(result)); if (error) return; moveresult(st,result); } else wrong_arg_in("lu"); } /**************** tridiagonalization *********************/ static double **mg; static void tridiag ( double *a, int n, int **rows) /***** tridiag tridiag. a with n rows and columns. r[] contains the new indices of the rows. *****/ { char *ram=newram,rh; double **m,maxi,*mh,lambda,h; int i,j,ipiv,ik,jk,k,*r; /* make a pointer array to the rows of m : */ m=(double **)ram; increase(ram,n*sizeof(double *)); for (i=0; imaxi) { maxi=h; ipiv=i; } } if (maximaxi) { maxi=h; ipiv=i; } } if (maxitype==s_matrix) { getmatrix(hd,&c,&r,&m); if (c!=r || c==0) wrong_arg(); result=new_matrix(c,c,""); if (error) return; result1=new_matrix(1,c,""); if (error) return; mr=matrixof(result); memmove(mr,m,(long)c*c*sizeof(double)); tridiag(mr,c,&rows); mr=matrixof(result1); for (i=0; itype==s_cmatrix) { getmatrix(hd,&c,&r,&m); if (c!=r || c==0) wrong_arg(); result=new_cmatrix(c,c,""); if (error) return; result1=new_matrix(1,c,""); if (error) return; mr=matrixof(result); memmove(mr,m,(long)c*c*(long)2*sizeof(double)); ctridiag(mr,c,&rows); mr=matrixof(result1); for (i=0; itype==s_matrix) { getmatrix(hd,&c,&r,&m); if (c!=r || c==0) wrong_arg(); result=new_matrix(c,c,""); if (error) return; result1=new_matrix(1,c+1,""); if (error) return; mr=matrixof(result); memmove(mr,m,(long)c*c*sizeof(double)); charpoly(mr,c,matrixof(result1)); } else if (hd->type==s_cmatrix) { getmatrix(hd,&c,&r,&m); if (c!=r || c==0) wrong_arg(); result=new_cmatrix(c,c,""); if (error) return; result1=new_cmatrix(1,c+1,""); if (error) return; mr=matrixof(result); memmove(mr,m,(long)c*c*(long)2*sizeof(double)); ccharpoly(mr,c,matrixof(result1)); } else wrong_arg(); moveresult(st,result1); } /***************** jacobi-givens eigenvalues **************/ static double rotate (double *m, int j, int k, int n) { double theta,t,s,c,tau,h,pivot; int l; pivot=*mat(m,n,j,k); if (fabs(pivot)type!=s_matrix) wrong_arg_in("jacobi"); getmatrix(hd,&r,&c,&m); if (r!=c) wrong_arg_in("jacobi"); if (r<2) { moveresult(st,hd); return; } hd1=new_matrix(r,r,""); if (error) return; m=matrixof(hd1); memmove(m,matrixof(hd),(long)r*r*sizeof(double)); while(1) { max=0.0; for (i=0; imax) max=neumax; if (max=0. iv[0]..iv[n-1] contain the variable indices of the rows, iv[n]..iv[n+m-1] contain the variable indices of the columns. a,b and c will be changed here. Results: -1 unfeasable, 1 unbounded, 0 solution found This procedure uses Bland's anticycling rule. */ { int i,i0,iv0,j,j0,jv0; double mi,h; /* Balance the lines */ for (i=0; iepsilon) { b[i]/=h; for (j=0; j=m) break; /* Search for a negative lambda */ for (j=0; j=n) return -1; /* Search for a possible column, take least variable index on tie */ jv0=iv[j]; j0=j; j++; for (; j=n) break; /* Search for a positive lambda */ for (i=0; iepsilon) break; if (i>=m) { for (j=0; jepsilon) { h=b[i]/a[i][j0]; if (htype!=s_matrix || hdb->type!=s_matrix || hdc->type!=s_matrix || dimsof(hdb)->c!=1 || dimsof(hdc)->r!=1) wrong_arg_in("simplex"); getmatrix(hda,&m,&n,&x); if (m!=dimsof(hdb)->r || n!=dimsof(hdc)->c) wrong_arg_in("simplex"); result=new_matrix(n,1,""); if (error) return; x=matrixof(result); for (i=0; i= 0.0 ? fabs(a) : -fabs(a)) static double maxarg1,maxarg2; #define FMAX(a,b) (maxarg1=(a),maxarg2=(b),(maxarg1) > (maxarg2) ?\ (maxarg1) : (maxarg2)) static int iminarg1,iminarg2; #define IMIN(a,b) (iminarg1=(a),iminarg2=(b),(iminarg1) < (iminarg2) ?\ (iminarg1) : (iminarg2)) static double sqrarg; #define SQR(a) ((sqrarg=(a)) == 0.0 ? 0.0 : sqrarg*sqrarg) static double pythag (double a, double b) { double absa,absb; absa=fabs(a); absb=fabs(b); if (absa > absb) return absa*sqrt(1.0+SQR(absb/absa)); else return (absb == 0.0 ? 0.0 : absb*sqrt(1.0+SQR(absa/absb))); } static void svdcmp(double **a, int m, int n, double w[], double **v) { int flag,i,its,j,jj,k,l=0,nm=0; double anorm,c,f,g,h,s,scale,x,y,z,*rv1; rv1=(double *)malloc((n+1)*sizeof(double)); g=scale=anorm=0.0; for (i=1;i<=n;i++) { l=i+1; rv1[i]=scale*g; g=s=scale=0.0; if (i <= m) { for (k=i;k<=m;k++) scale += fabs(a[k][i]); if (scale) { for (k=i;k<=m;k++) { a[k][i] /= scale; s += a[k][i]*a[k][i]; } f=a[i][i]; g = -SIGN(sqrt(s),f); h=f*g-s; a[i][i]=f-g; for (j=l;j<=n;j++) { for (s=0.0,k=i;k<=m;k++) s += a[k][i]*a[k][j]; f=s/h; for (k=i;k<=m;k++) a[k][j] += f*a[k][i]; } for (k=i;k<=m;k++) a[k][i] *= scale; } } w[i]=scale *g; g=s=scale=0.0; if (i <= m && i != n) { for (k=l;k<=n;k++) scale += fabs(a[i][k]); if (scale) { for (k=l;k<=n;k++) { a[i][k] /= scale; s += a[i][k]*a[i][k]; } f=a[i][l]; g = -SIGN(sqrt(s),f); h=f*g-s; a[i][l]=f-g; for (k=l;k<=n;k++) rv1[k]=a[i][k]/h; for (j=l;j<=m;j++) { for (s=0.0,k=l;k<=n;k++) s += a[j][k]*a[i][k]; for (k=l;k<=n;k++) a[j][k] += s*rv1[k]; } for (k=l;k<=n;k++) a[i][k] *= scale; } } anorm=FMAX(anorm,(fabs(w[i])+fabs(rv1[i]))); } for (i=n;i>=1;i--) { if (i < n) { if (g) { for (j=l;j<=n;j++) v[j][i]=(a[i][j]/a[i][l])/g; for (j=l;j<=n;j++) { for (s=0.0,k=l;k<=n;k++) s += a[i][k]*v[k][j]; for (k=l;k<=n;k++) v[k][j] += s*v[k][i]; } } for (j=l;j<=n;j++) v[i][j]=v[j][i]=0.0; } v[i][i]=1.0; g=rv1[i]; l=i; } for (i=IMIN(m,n);i>=1;i--) { l=i+1; g=w[i]; for (j=l;j<=n;j++) a[i][j]=0.0; if (g) { g=1.0/g; for (j=l;j<=n;j++) { for (s=0.0,k=l;k<=m;k++) s += a[k][i]*a[k][j]; f=(s/a[i][i])*g; for (k=i;k<=m;k++) a[k][j] += f*a[k][i]; } for (j=i;j<=m;j++) a[j][i] *= g; } else for (j=i;j<=m;j++) a[j][i]=0.0; ++a[i][i]; } for (k=n;k>=1;k--) { for (its=1;its<=30;its++) { flag=1; for (l=k;l>=1;l--) { nm=l-1; if ((double)(fabs(rv1[l])+anorm) == anorm) { flag=0; break; } if ((double)(fabs(w[nm])+anorm) == anorm) break; } if (flag) { c=0.0; s=1.0; for (i=l;i<=k;i++) { f=s*rv1[i]; rv1[i]=c*rv1[i]; if ((double)(fabs(f)+anorm) == anorm) break; g=w[i]; h=pythag(f,g); w[i]=h; h=1.0/h; c=g*h; s = -f*h; for (j=1;j<=m;j++) { y=a[j][nm]; z=a[j][i]; a[j][nm]=y*c+z*s; a[j][i]=z*c-y*s; } } } z=w[k]; if (l == k) { if (z < 0.0) { w[k] = -z; for (j=1;j<=n;j++) v[j][k] = -v[j][k]; } break; } if (its == 30) { output("No convergence in svd\n"); error=1; return; } x=w[l]; nm=k-1; y=w[nm]; g=rv1[nm]; h=rv1[k]; f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y); g=pythag(f,1.0); f=((x-z)*(x+z)+h*((y/(f+SIGN(g,f)))-h))/x; c=s=1.0; for (j=l;j<=nm;j++) { i=j+1; g=rv1[i]; y=w[i]; h=s*g; g=c*g; z=pythag(f,h); rv1[j]=z; c=f/z; s=h/z; f=x*c+g*s; g = g*c-x*s; h=y*s; y *= c; for (jj=1;jj<=n;jj++) { x=v[jj][j]; z=v[jj][i]; v[jj][j]=x*c+z*s; v[jj][i]=z*c-x*s; } z=pythag(f,h); w[j]=z; if (z) { z=1.0/z; c=f*z; s=h*z; } f=c*g+s*y; x=c*y-s*g; for (jj=1;jj<=m;jj++) { y=a[jj][j]; z=a[jj][i]; a[jj][j]=y*c+z*s; a[jj][i]=z*c-y*s; } } rv1[l]=0.0; rv1[k]=f; w[k]=x; } } free(rv1); } void msvd (header *hd) { header *st=hd,*hda,*hdw,*hdv; int m,n,i; double *mm; double **ma,**mv; hd=getvalue(hd); if (error) return; if (hd->type!=s_matrix) wrong_arg_in("svd"); getmatrix(hd,&m,&n,&mm); if (m<2 || n<2) wrong_arg_in("svd"); hda=new_matrix(m,n,""); if (error) return; hdw=new_matrix(1,n,""); if (error) return; hdv=new_matrix(n,n,""); if (error) return; memmove((char *)matrixof(hda),(char *)mm, n*sizeof(double)*m); ma=(double **)malloc(m*sizeof(double *)); for (i=0; i> 1; pp=g[m1]; qq=h[m1]; for (j=1;j<=m2;j++) { pt1=g[j]; pt2=g[k]; qt1=h[j]; qt2=h[k]; g[j]=pt1-pp*qt2; g[k]=pt2-pp*qt1; h[j]=qt1-qq*pt2; h[k--]=qt2-qq*pt1; } } output("Toeplitz failed.\n"); error=1; stop : free(g1); free(h1); } void msolvetoeplitz (header *hd) { header *st=hd,*hdb,*result; int n,i; double *m,*r; hdb=nextof(hd); hd=getvalue(hd); if (error) return; hdb=getvalue(hdb); if (error) return; if (hd->type!=s_matrix || dimsof(hd)->r!=1 || hdb->type!=s_matrix || dimsof(hdb)->c!=1) wrong_arg_in("toeplitzsolve"); n=dimsof(hdb)->r; if (n<2 || dimsof(hd)->c!=2*n-1) wrong_arg_in("toeplitzsolve"); result=new_matrix(n,1,""); if (error) return; r=(double *)malloc((2*n-1)*sizeof(double)); m=matrixof(hd); for (i=0; i<2*n-1; i++) r[i]=m[2*n-2-i]; toeplitz(r-1,matrixof(result)-1, matrixof(hdb)-1,n); free(r); if (error) return; moveresult(st,result); } void mtoeplitz (header *hd) { header *st=hd,*result; int i,n; double *m,*r; hd=getvalue(hd); if (error) return; if (hd->type!=s_matrix || dimsof(hd)->r!=1) wrong_arg_in("toeplitz"); n=dimsof(hd)->c; if (n<2 || n%2!=1) wrong_arg_in("toeplitz"); n=n/2+1; result=new_matrix(n,n,""); if (error) return; m=matrixof(result); r=matrixof(hd); for (i=0; i