/* INTERP_wts.c: interpolates a function whose values are known on a hypergrid * using either multidimensional linear interpolation or the * simplicial interpolation algorithm given in Algorithm 6.5 (p. 243) * of Judd, 1998, Numerical methods in Economics (MIT Press). This procedure differs from the procedure interp.g by computing a probability vector that represents the interpolation as a convex combination of the values of the function on the grid hypercube that contains the point s, i.e. it computes a vector p satisfying, p'vf=v(s), where p is nonnegative and sums to 1. John Rust, University of Maryland, June 2005 Inputs: s: point (dx1 vector) the the function is to be evaluated (via interpolation) vf: value function at grid points, arranged as an nx1 vector where n=n1*n2*...*nd where nj is the number of grid points in dimension j. p: probability weight vector to be computed. An (nx1) vector, same dimension as vf grid: gridpoints at which vf is given grid=(x(1,1),...,x(1,n1),x(2,1),...,x(2,n2),....,x(d,1),....,x(d,nd)) gridnum: dx1 vector with number of grid points used in each dimension gridnum=(n1,n2,...,nd) intmeth:interpolation method, 1 for simplicial interpolation 0 for linear interpolation Output: V(s): interpolated value of function at point s (this is the actual return of this function) p: vector that represents the interpolation, p'vf=v(s) (this is implicitly returns since p is passed as an input argument and its values are overwritten with the correct p vector, treated as an additional output) We assume the elements of grid and vf are stored in column order, i.e. k=1; do i1=1,...,n1 do i2=1,...,n2 ... do id=1,...,nd k=k+1; vf[k]=v(x(i1,1),x(i2,2),...,x(id,d)), where the grid points in each dimension satisfy: x(j,1) < x(j,2) < .... < x(j,nj) Required procedures: binsucc.c computes binary successor operation power.c computes binary exponential, 2^d kseq.c locates the sequence number in a multidimensional index mysort.c sorts a vector of numbers and returns permuated indices vertwt.c computes the probability weights that represent s as a convex combination of the vertices of the grid hypercube that contains s, the point to be interpolated Note: this routine is for 2 and higher dimensional problems only. Use vint1d.c for 1-dimensional problems. In 1-dimensional problems there is no difference between linear and simplicial interpolation. */ double interp_wts(double *s,double *p,double *vf,double *grid,int *gridnum,int d,int intmeth) { int i,j,ci,li,dd,n,k,lb,ub,lbs,twod,*indx,*arg,*argl,*lbound,*ubound; double ivf,cvf,lvf,*vsav,*wts,*swts; wts=(double *) malloc(d*sizeof(double)); lbound=(int *) malloc(d*sizeof(int)); ubound=(int *) malloc(d*sizeof(int)); arg=(int *) malloc(d*sizeof(int)); n=1; for (i=0; i 0) of the maximum grid point for the coordinate in question. */ for (i=0; i 0) { lb=1; for (j=0; j<=i-1; j++) { lb=lb+gridnum[j]; } } else { lb=1; } lb--; ub--; lbs=lb; if (s[i] > grid[ub]) { printf("Error interp.c: argument out of grid bounds\n"); printf("s[%2i]=%10.7f, max grid point=%10.7f\n",i,s[i],grid[ub]); free(wts); free(lbound); free(ubound); free(arg); return 0; } if (s[i] < grid[lb]) { printf("Error interp.c: argument out of grid bounds\n"); printf("s[%2i]=%10.7f, min grid point=%10.7f\n",i,s[i],grid[lb]); free(wts); free(lbound); free(ubound); free(arg); return 0; } for (j=lb; j<=ub; j++) { if (grid[j] >= s[i]) { ub=j; } } if (ub == lb) { ub=lb+1; } else { lb=ub-1; } lbound[i]=lb-lbs; ubound[i]=ub-lbs; wts[i]=(s[i]-grid[lb])/(grid[ub]-grid[lb]); } /* The following branch uses either simplicial interpolation or multidimensional linear interpolation depending on the value of the intmeth argument */ if (intmeth == 1) { /* Under simplicial interpolation, we start at the "top" of the hypercube (i.e. the largest gridpoint in the vector sense) and then move down the vertices of the hypercube for d more time according to the sorted weight vector, wts, above, and recursively taking convex combinations so that the final interpolated value is a convex combination of d+1 of the hypercube vectices. The gradient, however, will be discontinuous and constant within sub-simplices of the grid hypercube. */ swts=(double *) malloc(d*sizeof(double)); indx=(int *) malloc(d*sizeof(int)); argl=(int *) malloc(d*sizeof(int)); for (k=0; k0; dd--) { if (dd == d) { for(i=0; i