![]() ![]() |
![]() |
File: [Development] / JSOC / proj / libs / interpolate / finterpolate.c
(download)
Revision: 1.6, Tue Dec 6 18:11:03 2011 UTC (11 years, 5 months ago) by arta Branch: MAIN CVS Tags: Ver_LATEST, Ver_9-5, Ver_9-41, Ver_9-4, Ver_9-3, Ver_9-2, Ver_9-1, Ver_9-0, Ver_8-8, Ver_8-7, Ver_8-6, Ver_8-5, Ver_8-4, Ver_8-3, Ver_8-2, Ver_8-12, Ver_8-11, Ver_8-10, Ver_8-1, Ver_8-0, Ver_7-1, Ver_7-0, Ver_6-4, Ver_6-3, Ver_6-2, Ver_6-1, HEAD Changes since 1.5: +17 -9 lines Pass the path to the JSOC tree to the interpolation code - instead of using a hard-coded relative path. The interpolation code needs to locate data files in a directory that is relative to the interpolation source files. |
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <string.h> #include <math.h> #include <mkl.h> #include <omp.h> #include <sys/param.h> #include "finterpolate.h" #define minval(x,y) (((x) < (y)) ? (x) : (y)) #define maxval(x,y) (((x) < (y)) ? (y) : (x)) #define kInterpDataDir "proj/libs/interpolate/data" #define fint_wiener 1 #define fint_linear 2 #define fint_cubic_conv 3 static double sinc(double x) { if (fabs(x) < (1.e-10)) return 1.; else return sin(M_PI*x)/(M_PI*x); } int init_finterpolate_wiener_old( struct fint_struct *pars, int order, int edgemode, // 0 to go as far as you can with symmetric kernel // Otherwise go further (as set by extrapolate) float extrapolate, // How far to extrapolate int minorder, // Minimum order to use when approaching edge or beyond int nconst, // Number of polynomial constraints // 0 None, 1 for norm, 2 for linear preserved, etc. const char *path // to data files read by this function. ) { int status; int table=0; char filename[PATH_MAX]; snprintf(filename, sizeof(filename), "%s/%s/acor1d_80x100_double.txt", path, kInterpDataDir); status=init_finterpolate_wiener(pars,order,edgemode,extrapolate,minorder,nconst,table,&filename, path); return status; } int init_finterpolate_wiener( struct fint_struct *pars, int order, int edgemode, // 0 to go as far as you can with symmetric kernel // Otherwise go further (as set by extrapolate) float extrapolate, // How far to extrapolate int minorder, // Minimum order to use when approaching edge or beyond int nconst, // Number of polynomial constraints // 0 None, 1 for norm, 2 for linear preserved, etc. int cortable, // Which of the hardcoded tables to use. // 0 To use table pointed to by filenamep char **filenamep, // Pointer to name of file to read covariance from. // Set to actual file used if cortable>0 const char *path // to data files read by this function. ) { const int malign=32; const int nsubin0=100; const int maxoff=40; int i,j,k; int ishift,offset,order2,nextra,nshifts,shift0; FILE *fileptr; double *acor,*a,*rh,*a1b,*a1r,*coeffd; double bta1b,bta1r,c; double *b,*rhc,*bta1b1,*help; double xc,xp,sum; int info; char uplo[] = "U"; int ione = 1; double pmin,regul; int minorder1,curorder,imin,imax,icent,is0,i0,nrh; pars->method=fint_wiener; pars->kersx=NULL; if ((order%2) != 0) { printf("Order must be even!\n"); return 2; } if ((minorder%2) != 0) { printf("Minorder must be even!\n"); return 2; } if (nconst < 0) { printf("Number of constraints must be non-negative!\n"); return 2; } order2=order/2; if (edgemode==0) { // Only do area with symmetric set of points available nshifts=nsubin0+1; shift0=0; if (extrapolate!=0) { printf("Warning: Can't extrapolate for edgemode==0.\n"); extrapolate=0.0f; } } nextra=maxval(0,extrapolate)*nsubin0+2; shift0=(order2-1)*nsubin0+nextra; nshifts=(order-1)*nsubin0+2*nextra+1; icent=(nshifts-1)/2; // Center of range. icent=shift0+nsubin0/2 pars->edgemode=edgemode; pars->extrapolate=extrapolate; pars->order=order; pars->nshifts=nshifts; pars->shift0=shift0; pars->fover=(float)nsubin0; pars->nsub=nsubin0+1; pars->kersx=(float *)(MKL_malloc(nshifts*order*sizeof(float),malign)); regul=1/400./400.; pmin=regul; if ((cortable < 0) || (cortable > 1)) { printf("Illegal cortable passed to finterpolate!\n"); return 1; } if (cortable == 0) { pars->filename=strdup(*filenamep); } if (cortable == 1) { char dfile[PATH_MAX]; snprintf(dfile, sizeof(dfile), "%s/%s/acor1d_80x100_double.txt", path, kInterpDataDir); pars->filename=strdup(dfile); } fileptr = fopen (pars->filename, "r"); if (fileptr == NULL) { printf("File not found in finterpolate!\n"); return 2; } if (cortable != 0) { if (filenamep != NULL) { *filenamep=strdup(pars->filename); } } acor=(double *)(MKL_malloc((nsubin0*maxoff+1)*sizeof(double),malign)); for (i=0;i<nsubin0*maxoff+1;i++) fscanf(fileptr,"%lf",acor+i); fclose(fileptr); nrh=maxval(1,nconst); a=(double *)(MKL_malloc(order*order*sizeof(double),malign)); rh=(double *)(MKL_malloc(nrh*order*sizeof(double),malign)); a1r=(double *)(MKL_malloc(nrh*order*sizeof(double),malign)); a1b=(double *)(MKL_malloc(nrh*order*sizeof(double),malign)); coeffd=(double *)(MKL_malloc(order*sizeof(double),malign)); b=(double *)(MKL_malloc(nrh*order*sizeof(double),malign)); rhc=(double *)(MKL_malloc(nrh*sizeof(double),malign)); help=(double *)(MKL_malloc(nrh*sizeof(double),malign)); bta1b1=(double *)(MKL_malloc(nrh*nrh*sizeof(double),malign)); minorder1=minorder; if (edgemode == 0) minorder1=order; // Effectively ignore minorder for (curorder=minorder1;curorder<=order;curorder=curorder+2) { for (i=0;i<curorder;i++) { for (j=i;j<curorder;j++) { offset=nsubin0*(j-i); a[i*curorder+j]=acor[offset]; a[j*curorder+i]=acor[offset]; } a[i*curorder+i]=a[i*curorder+i]+regul; } dpotrf(uplo,&curorder,a,&curorder,&info); // Cholesky decomposition imin=icent-(order-curorder+1)*nsubin0/2; imax=icent+(order-curorder+1)*nsubin0/2; if (curorder == minorder) { // Extrapolate using minorder imin=0; imax=nshifts-1; } for (ishift=imin;ishift<=imax;ishift++) { // Find shift equivalent of first pixel to be used for interpolation // First find remainder is0=(ishift-shift0+nsubin0*2*order) % nsubin0; // Then find pixel is0=ishift-is0-nsubin0*(curorder/2-1); // Then limit to range of valid pixels is0=maxval(is0,icent-(order-1)*nsubin0/2); is0=minval(is0,icent+(order-1)*nsubin0/2-(curorder-1)*nsubin0); i0=(is0-icent+(order-1)*nsubin0/2)/nsubin0; //printf("%d %d %d %d %d %d\n",order,imin,imax,ishift,is0,i0); for (i=0;i<curorder;i++) { offset=ishift-(shift0+nsubin0*(i+i0-order/2+1)); if (offset<0) offset=-offset; rh[i]=acor[offset]+pmin*sinc((offset+0.0)/nsubin0); } // i switch (nconst) { case 0: // No constraints for (i=0;i<curorder;i++) coeffd[i]=rh[i]; dpotrs(uplo,&curorder,&ione,a,&curorder,coeffd,&curorder,&info); break; case 1: // Unit norm. Some tricks applied. for (i=0;i<curorder;i++) a1b[i]=1.; dpotrs(uplo,&curorder,&ione,a,&curorder,a1b,&curorder,&info); bta1b=0.; for (i=0;i<curorder;i++) bta1b=bta1b+a1b[i]; for (i=0;i<curorder;i++) a1r[i]=rh[i]; dpotrs(uplo,&curorder,&ione,a,&curorder,a1r,&curorder,&info); bta1r=0.0; for (i=0;i<curorder;i++) bta1r=bta1r+a1r[i]; c=(bta1r-1.)/bta1b; for (i=0;i<curorder;i++) coeffd[i]=a1r[i]-c*a1b[i]; break; default: // General case for (i=0;i<curorder;i++) { offset=ishift-(shift0+nsubin0*(i+i0-order/2+1)); xc=(offset+0.0)/nsubin0; xp=1.0; for (j=0;j<nconst;j++) { b[j*curorder+i]=xp; xp=xp*xc; } } rhc[0]=1; for (j=1;j<nconst;j++) rhc[j]=0; for (i=0;i<curorder*nconst;i++) a1b[i]=b[i]; dpotrs(uplo,&curorder,&nconst,a,&curorder,a1b,&curorder,&info); for (i=0;i<nconst;i++) { for (j=0;j<nconst;j++) { sum=0.0; for (k=0;k<curorder;k++) sum=sum+a1b[i*curorder+k]*b[j*curorder+k]; bta1b1[i*nconst+j]=sum; } } dpotrf(uplo,&nconst,bta1b1,&nconst,&info); // Cholesky decomposition for (i=0;i<nconst;i++) { sum=0.0; for (k=0;k<curorder;k++) sum=sum+a1b[i*curorder+k]*rh[k]; help[i]=sum-rhc[i]; } dpotrs(uplo,&nconst,&ione,bta1b1,&nconst,help,&nconst,&info); for (i=0;i<curorder;i++) a1r[i]=rh[i]; dpotrs(uplo,&curorder,&ione,a,&curorder,a1r,&curorder,&info); for (i=0;i<curorder;i++) { sum=0.0; for (k=0;k<nconst;k++) sum=sum+a1b[k*curorder+i]*help[k]; coeffd[i]=a1r[i]-sum; } break; } // Copy to output array // First zero unused entries for (i=0;i<order;i++) pars->kersx[ishift*order+i]=0.0f; for (i=0;i<curorder;i++) pars->kersx[ishift*order+i+i0]=(float)coeffd[i]; // for (i=0;i<curorder;i++) printf(" %f",coeffd[i]);printf("\n"); } // ishift } // order //for (ishift=0;ishift<nshifts;ishift++) { // for (i=0;i<order;i++) printf(" %f",pars->kersx[ishift*order+i]); // printf("\n"); //} MKL_free(acor); MKL_free(a); MKL_free(a1r); MKL_free(a1b); MKL_free(rh); MKL_free(coeffd); MKL_free(b); MKL_free(rhc); MKL_free(help); MKL_free(bta1b1); return 0; } int init_finterpolate_linear( struct fint_struct *pars, float extrapolate // How far to extrapolate ) { pars->method=fint_linear; pars->extrapolate=extrapolate; return 0; } int init_finterpolate_cubic_conv( struct fint_struct *pars, int edgemode, // 0 to go as far as you can with symmetric kernel // Otherwise go further (as set by extrapolate) float extrapolate // How far to extrapolate ) { pars->method=fint_cubic_conv; pars->edgemode=edgemode; pars->extrapolate=extrapolate; return 0; } int free_finterpolate( struct fint_struct *pars ) { if (pars->method==fint_wiener) { // Check for null if called after error in init. if (pars->kersx!=NULL) { MKL_free (pars->kersx); free (pars->filename); } } return 0; } int winterpolate( struct fint_struct *pars, float *image_in, float *xin, float *yin, float *image_out, int nxin, int nyin, int nleadin, int nx, int ny, int nlead, float fillval ) { int i,j,i1,j1; int order2; float *xker; const int ione = 1; int malign=32; int ixin,iyin,ixin1,iyin1; float *ixins,*iyins,*ixin1s,*iyin1s; float fxin1,fyin1,fxin2,fyin2; float *fxins,*fyins,*xinp,*yinp,*fxin1s,*fyin1s; float *xk1,*xk2,*yk1,*yk2; float *imp; float sum,sum1; float *kersx; int ixmax,iymax; float xmax,ymax; int order,shift0,edgemode; float extrapolate; float x,y,help; order=pars->order; kersx=pars->kersx; shift0=pars->shift0; edgemode=pars->edgemode; extrapolate=pars->extrapolate; order2=order/2; ixmax=nxin-order2; // Max index for first element of kernel iymax=nyin-order2; // Max index for first element of kernel xmax=(float)ixmax; ymax=(float)iymax; #pragma omp parallel default(none)\ private(ixins,iyins,fxins,fyins,ixin1s,iyin1s,fxin1s,fyin1s,xker) \ private (i,j,xinp,yinp,ixin,iyin,ixin1,iyin1,fxin1,fyin1,fxin2,fyin2,imp) \ private (xk1,xk2,yk1,yk2,sum,sum1,i1,j1,x,y,help) \ shared (pars,nlead,nx,ny,xin,yin,nleadin,nxin,nyin,image_in,image_out,order) \ shared (malign,order2,kersx,ixmax,iymax,xmax,ymax,shift0,edgemode,extrapolate,fillval) { // Needed to define parallel region ixins=(float *)(MKL_malloc(nx*sizeof(float),malign)); iyins=(float *)(MKL_malloc(nx*sizeof(float),malign)); fxins=(float *)(MKL_malloc(nx*sizeof(float),malign)); fyins=(float *)(MKL_malloc(nx*sizeof(float),malign)); ixin1s=(float *)(MKL_malloc(nx*sizeof(float),malign)); iyin1s=(float *)(MKL_malloc(nx*sizeof(float),malign)); fxin1s=(float *)(MKL_malloc(nx*sizeof(float),malign)); fyin1s=(float *)(MKL_malloc(nx*sizeof(float),malign)); xker=(float *)(MKL_malloc(order*sizeof(float),malign)); // This awful code basically hardcodes the common cases and allows the // compiler to optimize the code for a significant speed improvement switch(order) { case 2: #define OOO1 2 #define OOO2 1 #include "finterpolate.include" #undef OOO1 #undef OOO2 break; case 4: #define OOO1 4 #define OOO2 2 #include "finterpolate.include" #undef OOO1 #undef OOO2 break; case 6: #define OOO1 6 #define OOO2 3 #include "finterpolate.include" #undef OOO1 #undef OOO2 break; case 8: #define OOO1 8 #define OOO2 4 #include "finterpolate.include" #undef OOO1 #undef OOO2 break; case 10: #define OOO1 10 #define OOO2 5 #include "finterpolate.include" #undef OOO1 #undef OOO2 break; case 12: #define OOO1 12 #define OOO2 6 #include "finterpolate.include" #undef OOO1 #undef OOO2 break; case 14: #define OOO1 14 #define OOO2 7 #include "finterpolate.include" #undef OOO1 #undef OOO2 break; case 16: #define OOO1 16 #define OOO2 8 #include "finterpolate.include" #undef OOO1 #undef OOO2 break; case 18: #define OOO1 18 #define OOO2 9 #include "finterpolate.include" #undef OOO1 #undef OOO2 break; case 20: #define OOO1 20 #define OOO2 10 #include "finterpolate.include" #undef OOO1 #undef OOO2 break; case 22: #define OOO1 22 #define OOO2 11 #include "finterpolate.include" #undef OOO1 #undef OOO2 break; case 24: #define OOO1 24 #define OOO2 12 #include "finterpolate.include" #undef OOO1 #undef OOO2 break; case 26: #define OOO1 26 #define OOO2 13 #include "finterpolate.include" #undef OOO1 #undef OOO2 break; case 28: #define OOO1 28 #define OOO2 14 #include "finterpolate.include" #undef OOO1 #undef OOO2 break; case 30: #define OOO1 30 #define OOO2 15 #include "finterpolate.include" #undef OOO1 #undef OOO2 break; case 32: #define OOO1 32 #define OOO2 16 #include "finterpolate.include" #undef OOO1 #undef OOO2 break; // If not hardcoded do general calculation default: #define OOO1 order #define OOO2 order2 #include "finterpolate.include" #undef OOO1 #undef OOO2 break; } MKL_free(xker); MKL_free(ixins); MKL_free(iyins); MKL_free(fxins); MKL_free(fyins); MKL_free(ixin1s); MKL_free(iyin1s); MKL_free(fxin1s); MKL_free(fyin1s); } // End of parallel region return 0; } int linterpolate( float *image_in, float *xin, float *yin, float *image_out, int nxin, int nyin, int nleadin, int nx, int ny, int nlead, float extrapolate, float fillval ) { int i,j; int malign=32; int ixin,iyin; float *ixins,*iyins; float fxin1,fyin1,fxin2,fyin2; float *xinp,*yinp; float *imp; float xmin,xmax,ymin,ymax; xmin=-extrapolate; xmax=nxin-1.0f+extrapolate; ymin=-extrapolate; ymax=nyin-1.0f+extrapolate; #pragma omp parallel default(none) \ private(ixins,iyins,i,j,xinp,yinp,ixin,iyin,fxin1,fyin1,fxin2,fyin2,imp) \ shared(image_in,xin,yin,image_out,extrapolate,fillval) \ shared(nx,ny,nlead,nxin,nyin,nleadin) \ shared(malign,xmin,xmax,ymin,ymax) { // Needed to define parallel region ixins=(float *)(MKL_malloc(nx*sizeof(float),malign)); iyins=(float *)(MKL_malloc(nx*sizeof(float),malign)); #pragma omp for for (j=0; j<ny; j++) { xinp=xin+j*nlead; vsFloor(nx,xinp,ixins); yinp=yin+j*nlead; vsFloor(nx,yinp,iyins); for (i=0; i<nx; i++) { ixin=(int)ixins[i]; // Integer pixel to interpolate to iyin=(int)iyins[i]; // Integer pixel to interpolate to if ((ixin>=0) && (ixin <(nxin-1)) && (iyin>=0) && (iyin <(nyin-1))) { // Normal case fxin1=xinp[i]-ixin; fyin1=yinp[i]-iyin; fxin2=1.0f-fxin1; fyin2=1.0f-fyin1; imp=image_in+ixin+nleadin*iyin; /* Brute force addition */ image_out[i+nlead*j]=fyin2*(fxin2*imp[0]+fxin1*imp[1])+ fyin1*(fxin2*imp[nleadin]+fxin1*imp[nleadin+1]); } // if else { if ((xinp[i]>=xmin) && (xinp[i]<=xmax) && (yinp[i]>=ymin) && (yinp[i]<=ymax)) { // Extrapolating or point exactly at edge // Move ixin and iyin inside of array ixin=maxval(0,minval(ixin,nxin-2)); iyin=maxval(0,minval(iyin,nyin-2)); fxin1=xinp[i]-ixin; fyin1=yinp[i]-iyin; fxin2=1.0f-fxin1; fyin2=1.0f-fyin1; imp=image_in+ixin+nleadin*iyin; /* Brute force addition */ image_out[i+nlead*j]=fyin2*(fxin2*imp[0]+fxin1*imp[1])+ fyin1*(fxin2*imp[nleadin]+fxin1*imp[nleadin+1]); } else { // Outside of array image_out[i+nlead*j]=fillval; } } } // i= } //j= MKL_free(ixins); MKL_free(iyins); } // End of parallel region return 0; } int ccinterpolate( // Cubic convolution interpolation float *image_in, float *xin, float *yin, float *image_out, int nxin, int nyin, int nleadin, int nx, int ny, int nlead, int edgemode, float extrapolate, float fillval ) { int i,j,i1; float xker[4],yker[4]; int malign=32; int ixin,iyin; float *ixins,*iyins; float *xinp,*yinp; float *imp; float sum; float s,s2; float xmin,xmax,ymin,ymax; if (edgemode == 0) { xmin=1.0f; xmax=nxin-2.0f; ymin=1.0f; ymax=nyin-2.0f; } else { xmin=-extrapolate; xmax=nxin-1.0f+extrapolate; ymin=-extrapolate; ymax=nyin-1.0f+extrapolate; } #pragma omp parallel default(none) \ private(ixins,iyins,i,j,xinp,yinp,ixin,iyin,imp,s,s2,xker,yker,sum,i1) \ shared(image_in,xin,yin,image_out) \ shared(nxin,nyin,nleadin,nx,ny,nlead,extrapolate,fillval) \ shared(malign,xmin,xmax,ymin,ymax) { // Needed to define parallel region ixins=(float *)(MKL_malloc(nx*sizeof(float),malign)); iyins=(float *)(MKL_malloc(nx*sizeof(float),malign)); #pragma omp for for (j=0; j<ny; j++) { xinp=xin+j*nlead; vsFloor(nx,xinp,ixins); yinp=yin+j*nlead; vsFloor(nx,yinp,iyins); for (i=0; i<nx; i++) { ixin=(int)ixins[i]; // Integer pixel to interpolate to iyin=(int)iyins[i]; // Integer pixel to interpolate to if ((ixin>=1) && (ixin <(nxin-2)) && (iyin>=1) && (iyin <(nyin-2))) { // RML kernel calculation based on fc3kernel in winterpolate_old.c // Kernels are unnormalized and need to be divided by 2 s=xinp[i]-ixin; s2 = s*s; xker[0] = -s*(1.0f - s*(2.0f - s)); xker[1] = 2.0f - s2*(5.0f - 3.0f*s); xker[2] = s*(1.0f + s*(4.0f - 3.0f*s)); xker[3] = -s2*(1.0f-s); s=yinp[i]-iyin; s2 = s*s; yker[0] = -s*(1.0f - s*(2.0f - s)); yker[1] = 2.0f - s2*(5.0f - 3.0f*s); yker[2] = s*(1.0f + s*(4.0f - 3.0f*s)); yker[3] = -s2*(1.0f-s); imp=image_in+ixin-1+nleadin*(iyin-1); /* Brute force addition */ sum=0.0f; for (i1=0; i1<4; i1++) { sum=sum+yker[i1]*(xker[0]*imp[0]+xker[1]*imp[1]+xker[2]*imp[2]+xker[3]*imp[3]); imp=imp+nleadin; } image_out[i+nlead*j]=sum/4; } // if else { if ((xinp[i]>=xmin) && (xinp[i]<=xmax) && (yinp[i]>=ymin) && (yinp[i]<=ymax)) { // Extrapolating or point exactly at edge // Move ixin and iyin inside of array ixin=maxval(1,minval(ixin,nxin-3)); iyin=maxval(1,minval(iyin,nyin-3)); // RML kernel calculation based on fc3kernel in winterpolate_old.c // Kernels are unnormalized and need to be divided by 2 s=xinp[i]-ixin; s2 = s*s; xker[0] = -s*(1.0f - s*(2.0f - s)); xker[1] = 2.0f - s2*(5.0f - 3.0f*s); xker[2] = s*(1.0f + s*(4.0f - 3.0f*s)); xker[3] = -s2*(1.0f-s); s=yinp[i]-iyin; s2 = s*s; yker[0] = -s*(1.0f - s*(2.0f - s)); yker[1] = 2.0f - s2*(5.0f - 3.0f*s); yker[2] = s*(1.0f + s*(4.0f - 3.0f*s)); yker[3] = -s2*(1.0f-s); imp=image_in+ixin-1+nleadin*(iyin-1); /* Brute force addition */ sum=0.0f; for (i1=0; i1<4; i1++) { sum=sum+yker[i1]*(xker[0]*imp[0]+xker[1]*imp[1]+xker[2]*imp[2]+xker[3]*imp[3]); imp=imp+nleadin; } image_out[i+nlead*j]=sum/4; } else { // Outside of array image_out[i+nlead*j]=fillval; } } } // i= } //j= MKL_free(ixins); MKL_free(iyins); } // End of parallel region return 0; } int finterpolate( struct fint_struct *pars, float *image_in, float *xin, float *yin, float *image_out, int nxin, int nyin, int nleadin, int nx, int ny, int nlead, float fillval ) { int status; switch (pars->method) { case fint_wiener: status=winterpolate(pars,image_in,xin,yin,image_out,nxin,nyin,nleadin,nx,ny,nlead,fillval); break; case fint_linear: status=linterpolate(image_in,xin,yin,image_out,nxin,nyin,nleadin,nx,ny,nlead,pars->extrapolate,fillval); break; case fint_cubic_conv: status=ccinterpolate(image_in,xin,yin,image_out,nxin,nyin,nleadin,nx,ny,nlead,pars->edgemode,pars->extrapolate,fillval); break; default: status=1; break; } return status; } char *finterpolate_version() // Returns CVS version of finterpolate.c { return strdup("$Id: finterpolate.c,v 1.6 2011/12/06 18:11:03 arta Exp $"); }
Karen Tian |
Powered by ViewCVS 0.9.4 |