Exemple #1
0
Color ray_shade(int level, Real w, Ray v, RContext *rc, Object *ol)
{
  Inode *i = ray_intersect(ol, v);
  if (i != NULL) { Light *l; Real wf;
    Material *m = i->m;
    Vector3 p = ray_point(v, i->t); 
    Cone  recv = cone_make(p, i->n, PIOVER2);
    Color c = c_mult(m->c, c_scale(m->ka, ambient(rc)));
    rc->p = p;

    for (l = rc->l; l != NULL; l = l->next) 
      if ((*l->transport)(l, recv, rc) && (wf = shadow(l, p, ol)) > RAY_WF_MIN)
	c = c_add(c, c_mult(m->c,
		     c_scale(wf * m->kd * v3_dot(l->outdir,i->n), l->outcol)));

    if (level++ < MAX_RAY_LEVEL) {
      if ((wf = w * m->ks) > RAY_WF_MIN) {
	Ray r = ray_make(p, reflect_dir(v.d, i->n));
        c = c_add(c, c_mult(m->s,
		     c_scale(m->ks, ray_shade(level, wf, r, rc, ol))));
      }
      if ((wf = w * m->kt) > RAY_WF_MIN) {
	Ray t = ray_make(p, refract_dir(v.d, i->n, (i->enter)? 1/m->ir: m->ir));
	if (v3_sqrnorm(t.d) > 0) {
	  c = c_add(c, c_mult(m->s,
		       c_scale(m->kt, ray_shade(level, wf, t, rc, ol))));
	}
      }
    }
    inode_free(i); 
    return c;
  } else {
    return BG_COLOR;
  }
}
Exemple #2
0
Color textured_plastic(RContext *rc)
{
  Color c, ct = texture_map(rc->m->tinfo, rc->t);

  c = c_add(c_mult(ct, c_add(c_scale(rc->m->ka, ambient(rc)),
                             c_scale(rc->m->kd, diffuse(rc)))),
            c_mult(rc->m->s, c_scale(rc->m->ks, specular(rc))));
  return c;
}
Exemple #3
0
void polymult (header *hd)
{	header *st=hd,*hd1,*result;
	int c,c1,c2,i,r,j,k;
	double *m1,*m2,*mr,x;
	complex *mc1,*mc2,*mcr,xc,hc;
	interval *mi1,*mi2,*mir,xi,hi;
	hd1=next_param(st);
	equal_params_2(&hd,&hd1); if (error) return;
	getmatrix(hd,&r,&c1,&m1); if (r!=1) wrong_arg();
	getmatrix(hd1,&r,&c2,&m2); if (r!=1) wrong_arg();
	if ((LONG)c1+c2-1>INT_MAX) wrong_arg();
	c=c1+c2-1;
	if (iscomplex(hd))
	{	mc1=(complex *)m1; mc2=(complex *)m2;
		result=new_cmatrix(1,c,""); if (error) return;
		mcr=(complex *)matrixof(result);
		c_copy(xc,*mc1); mc1++;
		for (i=0; i<c2; i++) c_mult(xc,mc2[i],mcr[i]);
		for (j=1; j<c1; j++)
		{	c_copy(xc,*mc1); mc1++;
			for (k=j,i=0; i<c2-1; i++,k++)
			{	c_mult(xc,mc2[i],hc);
				c_add(hc,mcr[k],mcr[k]);
			}
			c_mult(xc,mc2[i],mcr[k]);
		}
	}
	else if (isinterval(hd))
	{	mi1=(interval *)m1; mi2=(interval *)m2;
		result=new_imatrix(1,c,""); if (error) return;
		mir=(interval *)matrixof(result);
		i_copy(xi,*mi1); mi1++;
		for (i=0; i<c2; i++) i_mult(xi,mi2[i],mir[i]);
		for (j=1; j<c1; j++)
		{	i_copy(xi,*mi1); mi1++;
			for (k=j,i=0; i<c2-1; i++,k++)
			{	i_mult(xi,mi2[i],hi);
				c_add(hi,mir[k],mir[k]);
			}
			c_mult(xi,mi2[i],mir[k]);
		}
	}
	else if (isreal(hd))
	{	result=new_matrix(1,c,""); if (error) return;
		mr=matrixof(result);
		x=*m1++;
		for (i=0; i<c2; i++) mr[i]=x*m2[i];
		for (j=1; j<c1; j++)
		{	x=*m1++;
			for (k=j,i=0; i<c2-1; i++,k++) mr[k]+=x*m2[i];
			mr[k]=x*m2[i];
		}
	}
	else wrong_arg();
	moveresult(st,result);
}
Exemple #4
0
static struct polynom *pol_div(struct polynom *p,struct polynom *q,struct polynom *p1,struct polynom *p2)
        {
        int i,j;
        struct complex z,z1;

		z.x=0; z.y=0; // RS 7.2.2013
        p->n=p1->n-p2->n;
        if (p->n<0)
            {
            sur_print("\nDegree of dividend < Degree of divisor");
            WAIT; return(p);
            }
        for (i=0; i<=p->n; ++i)
            p->a[i].x=p->a[i].y=0.0;
        for (i=0; i<=p1->n; ++i)
            { q->a[i].x=p1->a[i].x; q->a[i].y=p1->a[i].y; }

        for (i=p1->n; i>=p2->n; --i)
            {
            if (c_zero(&(q->a[i]))) continue;
            c_div(&z,&(q->a[i]),&(p2->a[p2->n]));
            p->a[i-p2->n].x=z.x; p->a[i-p2->n].y=z.y;
            q->a[i].x=q->a[i].y=0.0;
            for (j=i-1; j>=i-p2->n; --j)
                c_sub(&(q->a[j]),&(q->a[j]),
                      c_mult(&z1,&z,&(p2->a[p2->n-i+j])));
            }
        i=p2->n-1;
        while (c_zero(&(q->a[i])) && i>0) --i;
        q->n=i;
        return(p);
        }
Exemple #5
0
void fft (double *a, int n, int signum)
{	complex z;
	double h;
	int i;
	
	if (n==0) return;
	nn=n;

	ram=newram;
	if (!freeram(2*(1+n)*sizeof(complex))) outofram();
	ff=(complex *)a;
	zz=(complex *)ram;
	ram+=n*sizeof(complex);
	fh=(complex *)ram;
	ram+=n*sizeof(complex);

	/* compute zz[k]=e^{-2*pi*i*k/n}, k=0,...,n-1 */
	h=2*M_PI/n; z[0]=cos(h); z[1]=signum*sin(h);
	zz[0][0]=1; zz[0][1]=0;
	for (i=1; i<n; i++)
	{	if (i%16) { zz[i][0]=cos(i*h); zz[i][1]=signum*sin(i*h); }
		else c_mult(zz[i-1],z,zz[i]);
	}
	rfft(0,n,1,1);
	if (signum==1)
		for (i=0; i<n; i++)
		{	ff[i][0]*=n; ff[i][1]*=n;
		}
}
Exemple #6
0
Color *radiosity_prog(int n, Poly **p, Color *e, Color *rho)
{
  int src, rcv, iter = 0;
  Real ff, mts, *a = NEWTARRAY(n, Real);
  Color d, *dm = NEWTARRAY(n, Color);
  Color ma, *m = NEWTARRAY(n, Color);
	
  initialize(n, m, dm, a, p, e);
  while (iter-- < max_iter) {
    src = select_shooter(n, dm, a);
    if (converged(src, dm))
      break;
    for (rcv = 0; rcv < n; rcv++) {
      if (rcv == src || (ff = formfactor(src, rcv, n, p, a)) < REL_EPS)
	continue;
      d = c_scale(ff, c_mult(rho[rcv], dm[src]));

      m[rcv] = c_add(m[rcv], d);
      dm[rcv] = c_add(dm[rcv], d);
    }
    dm[src] = c_make(0,0,0);
  }
  ma = ambient_rad(n, dm, a);
  for (rcv = 0; rcv < n; rcv++)
    m[rcv] = c_add(m[rcv], ma);
  efree(a), efree(dm);
  return m;
}
Exemple #7
0
// 1D Fourier Transform: fft_1d_helper(x, N, stride, y)
// if N > 1 then
//    1. take the FFT of the even elements in x, and store it in the first half of y
//         x' = x
//         stride' = 2 * stride
//         y' = y
//    2. take the FFT of the odd elements in x, and store it in the second half of y
//         x' = x + stride
//         stride' = 2 * stride
//         y' = y + N/2
//    3. for each frequency step k in 0 ... N/2
//       i. compute the component at Wkn = exp(-j*2*pi/N * k)
//          y[k] = y[k] + Wkn * y[k + N/2]
//       ii. compute the component at Wkn = exp(-j*2*pi/N * (k + N/2))
//          y[k + N/2] = y[k] + Wkn * y[k + N/2]
// otherwise just return the element at x[0]
void fft_1d_helper(complex* x, int N, int stride, complex* y,
                   complex* Wkn, int Wkn_stride){
  if(N > 1) {
    fft_1d_helper(x, N/2, 2*stride, y, Wkn, 2*Wkn_stride);
    fft_1d_helper(x + stride, N/2, 2*stride, y + N/2, Wkn, 2*Wkn_stride);
    
    for(int k=0; k<N/2; k++) {
      complex Wkn1 = Wkn[k*Wkn_stride];
      complex Wkn2 = Wkn[(k + N/2)*Wkn_stride];
      complex yk1 = c_add(y[k], c_mult(Wkn1, y[k + N/2]));
      complex yk2 = c_add(y[k], c_mult(Wkn2, y[k + N/2]));
      y[k] = yk1;
      y[k+N/2] = yk2;
    }
  } else {
    y[0] = x[0];
  }
}
Exemple #8
0
void polyzeros (header *hd)
{	header *st=hd,*result;
	int i,j,r,c;
	double *m,*mr,x;
	complex *mc,*mcr,xc,hc;
	hd=getvalue(hd); if (error) return;
	if (hd->type==s_real || hd->type==s_matrix)
	{	getmatrix(hd,&r,&c,&m);
		if (r!=1) wrong_arg();
		result=new_matrix(1,c+1,""); if (error) return;
		mr=matrixof(result);
		mr[0]=-m[0]; mr[1]=1.0;
		for (i=1; i<c; i++)
		{	x=-m[i]; mr[i+1]=1.0;
			for (j=i; j>=1; j--) mr[j]=mr[j-1]+x*mr[j];
			mr[0]*=x;
		}
	}
	else if (hd->type==s_complex || hd->type==s_cmatrix)
	{	getmatrix(hd,&r,&c,&m); mc=(complex *)m;
		if (r!=1) wrong_arg();
		result=new_cmatrix(1,c+1,""); if (error) return;
		mcr=(complex *)matrixof(result);
		mcr[0][0]=-mc[0][0]; mcr[0][1]=-mc[0][1];
		mcr[1][0]=1.0; mcr[1][1]=0.0;
		for (i=1; i<c; i++)
		{	xc[0]=-mc[i][0]; xc[1]=-mc[i][1];
			mcr[i+1][0]=1.0; mcr[i+1][1]=0.0;
			for (j=i; j>=1; j--) 
			{	c_mult(xc,mcr[j],hc);
				c_add(hc,mcr[j-1],mcr[j]);
			}
			c_mult(xc,mcr[0],mcr[0]);
		}
	}
	else wrong_arg();
	moveresult(st,result);
}
Exemple #9
0
static struct complex *pol_value(
struct polynom *p,
struct complex *z,  /* pointer to argument */
struct complex *v   /* pointer to function value */
)
        {
        int i;

        v->x=p->a[p->n].x;
        v->y=p->a[p->n].y;
        for (i=p->n-1; i>=0; --i)
            c_add(v,&(p->a[i]),c_mult(v,z,v));
        return(v);
        }
Exemple #10
0
void polydd (header *hd)
{	header *st=hd,*hd1,*result;
	int c1,c2,i,j,r;
	double *m1,*m2,*mr,x;
	complex *mc1,*mc2,*mcr,hc,xc;
	hd1=next_param(st);
	equal_params_2(&hd,&hd1); if (error) return;
	getmatrix(hd,&r,&c1,&m1); if (r!=1) wrong_arg();
	getmatrix(hd1,&r,&c2,&m2); if (r!=1) wrong_arg();
	if (c1!=c2) wrong_arg();
	if (iscomplex(hd)) /* complex values */
	{	mc1=(complex *)m1; mc2=(complex *)m2;
		result=new_cmatrix(1,c1,""); if (error) return;
		mcr=(complex *)matrixof(result);
		c_copy(mcr[c1-1],mc2[c1-1]);
		for (i=c1-2; i>=0; i--)
		{	c_copy(xc,mc1[i]);
			c_mult(xc,mcr[i+1],hc);
			c_sub(mc2[i],hc,mcr[i]);
			for (j=i+1; j<c1-1; j++) 
			{	c_mult(xc,mcr[j+1],hc);
				c_sub(mcr[j],hc,mcr[j]);
			}
		}
	}
	else
	{	result=new_matrix(1,c1,""); if (error) return;
		mr=matrixof(result);
		mr[c1-1]=m2[c1-1];
		for (i=c1-2; i>=0; i--)
		{	x=m1[i];
			mr[i]=m2[i]-x*mr[i+1];
			for (j=i+1; j<c1-1; j++) mr[j]=mr[j]-x*mr[j+1];
		}
	}
	moveresult(st,result);
}
Exemple #11
0
static struct polynom *pol_mult(struct polynom *p,struct polynom *p1,struct polynom *p2)
        {
        int i,j;
        struct complex tulo;

        p->n=p1->n+p2->n;
        if (p->n>MAXN-1) { pol_dim_overflow(); return(p); }

        for (i=0; i<=p->n; ++i)
            p->a[i].x=p->a[i].y=0.0;
        for (i=0; i<=p1->n; ++i)
            for (j=0; j<=p2->n; ++j)
                c_add(&(p->a[i+j]),&(p->a[i+j]),
                          c_mult(&tulo,&(p1->a[i]),&(p2->a[j])));

        return(p);
        }
Exemple #12
0
void rfft (long m0, long p0, long q0, long n)
/***** rfft 
	make a fft on x[m],x[m+q0],...,x[m+(p0-1)*q0] (p points).
	one has xi_p0 = xi_n^n = zz[n] ; i.e., p0*n=nn.
*****/
{	long p,q,m,l;
	long mh,ml;
	int found=0;
	complex sum,h;
	if (p0==1) return;
	if (test_key()==escape) { error=301; return; }
	if (p0%2==0) { p=p0/2; q=2; }
	else
	{	q=3;
		while (q*q<=p0)
		{	if (p0%q==0) 
			{	found=1; break; }
			q+=2;
		}
		if (found) p=p0/q;
		else { q=p0; p=1; }
	}
	if (p>1) for (m=0; m<q; m++) 
		rfft((m0+m*q0)%nn,p,q*q0,nn/p);
	mh=m0;
	for (l=0; l<p0; l++)
	{	ml=l%p;
		c_copy(sum,ff[(m0+ml*q*q0)%nn]);
		for (m=1; m<q; m++)
		{	c_mult(ff[(m0+(m+ml*q)*q0)%nn],zz[(n*l*m)%nn],h);
			c_add(sum,h,sum);
		}
		sum[0]/=q; sum[1]/=q;
		c_copy(fh[mh],sum);
		mh+=q0; if (mh>=nn) mh-=nn;
	}
	for (l=0; l<p0; l++)
	{	c_copy(ff[m0],fh[m0]);
		m0+=q0;
	}
}
Exemple #13
0
/*{{{  subtract(transform_info_ptr tinfo)*/
METHODDEF DATATYPE *
subtract(transform_info_ptr tinfo) {
 struct subtract_storage *local_arg=(struct subtract_storage *)tinfo->methods->local_storage;
 transform_argument *args=tinfo->methods->arguments;
 transform_info_ptr side_tinfo= &local_arg->side_tinfo;
 int channels1, channels2, points1, points2, channel1, channel2, point1, point2;
 int itempart, offset1, offset2;
 int itemskip=1+tinfo->leaveright;
 int side_itemskip=1+side_tinfo->leaveright;

 if (side_tinfo->tsdata==NULL || args[ARGS_EVERY].is_set) {
  /*{{{  (Try to) Read the next subtract epoch */
  if (side_tinfo->tsdata!=NULL) free_tinfo(side_tinfo);
  if ((side_tinfo->tsdata=(*side_tinfo->methods->transform)(side_tinfo))!=NULL) {
   multiplexed(side_tinfo);
  }
  /*}}}  */
 }

 if (side_tinfo->tsdata==NULL) {
  ERREXIT(tinfo->emethods, "subtract: Last subtract epoch couldn't be read.\n");
 }
 if (local_arg->ttest) {
  if (itemskip!=3 && itemskip!=4) {
   ERREXIT(tinfo->emethods, "subtract: Not 3 or 4 values per item in tinfo to calculate t comparison.\n");
  }
  if (side_itemskip!=3 && side_itemskip!=4) {
   ERREXIT(tinfo->emethods, "subtract: Not 3 or 4 values per item in side_tinfo to calculate t comparison.\n");
  }
 } else {
  if (tinfo->itemsize!=side_tinfo->itemsize) {
   /* Note we accept different itemskip values - itemskip takes precedence over side_itemskip. */
   ERREXIT(tinfo->emethods, "subtract: Item counts of input epochs don't match.\n");
  }
  if (local_arg->type==SUBTRACT_TYPE_COMPLEXMULTIPLY || local_arg->type==SUBTRACT_TYPE_COMPLEXDIVIDE) {
   if (tinfo->itemsize%2!=0) {
    ERREXIT(tinfo->emethods, "subtract: Item size must be divisible by 2 for complex operations.\n");
   }
   itemskip=side_itemskip=2;
  } else {
   /* If leaveright is set, we still want to do something with all single items: */
   itemskip=side_itemskip=1;
  }
 }
 if (args[ARGS_RECYCLE_CHANNELS].is_set && tinfo->nr_of_channels>side_tinfo->nr_of_channels) {
  channels1=tinfo->nr_of_channels;
  channels2=side_tinfo->nr_of_channels;
 } else {
  channels1=channels2=min(tinfo->nr_of_channels, side_tinfo->nr_of_channels);
 }
 if (args[ARGS_RECYCLE_POINTS].is_set && tinfo->nr_of_points>side_tinfo->nr_of_points) {
  points1=tinfo->nr_of_points;
  points2=side_tinfo->nr_of_points;
 } else {
  points1=points2=min(tinfo->nr_of_points, side_tinfo->nr_of_points);
 }
 multiplexed(tinfo);
 for (point1=point2=0; point1<points1; point1++, point2++) {
  /* Flip point2 back to the start if it hits the end */
  if (point2==points2) point2=0;
  for (channel1=channel2=0; channel1<channels1; channel1++, channel2++) {
   /* Flip channel2 back to the start if it hits the end */
   if (channel2==channels2) channel2=0;
   for (itempart=0; itempart<tinfo->itemsize; itempart+=itemskip) {
    offset1=(point1*tinfo->nr_of_channels+channel1)*tinfo->itemsize+itempart;
    offset2=(point2*side_tinfo->nr_of_channels+channel2)*side_tinfo->itemsize+itempart;
    switch (local_arg->type) {
     case SUBTRACT_TYPE_ADD:
      tinfo->tsdata[offset1]+=side_tinfo->tsdata[offset2];
      break;
     case SUBTRACT_TYPE_MEAN:
      /* Work identically here regarding 'sum-only' items as average.c */
      if (itempart<tinfo->itemsize-tinfo->leaveright) {
       tinfo->tsdata[offset1]=(tinfo->tsdata[offset1]+side_tinfo->tsdata[offset2])/2;
      } else {
       /* Simple sum for the leaveright (`sum-only') items */
       tinfo->tsdata[offset1]+=side_tinfo->tsdata[offset2];
      }
      break;
     case SUBTRACT_TYPE_WMEAN:
      /* Work identically here regarding 'sum-only' items as average.c */
      if (itempart<tinfo->itemsize-tinfo->leaveright) {
       tinfo->tsdata[offset1]=(tinfo->tsdata[offset1]*tinfo->nrofaverages+side_tinfo->tsdata[offset2]*side_tinfo->nrofaverages)/(tinfo->nrofaverages+side_tinfo->nrofaverages);
      } else {
       /* Non-weighted sum for the leaveright (`sum-only') items */
       tinfo->tsdata[offset1]+=side_tinfo->tsdata[offset2];
      }
      break;
     case SUBTRACT_TYPE_SUBTRACT:
      tinfo->tsdata[offset1]-=side_tinfo->tsdata[offset2];
      break;
     case SUBTRACT_TYPE_MULTIPLY:
      tinfo->tsdata[offset1]*=side_tinfo->tsdata[offset2];
      break;
     case SUBTRACT_TYPE_DIVIDE:
      tinfo->tsdata[offset1]/=side_tinfo->tsdata[offset2];
      break;
     case SUBTRACT_TYPE_COMPLEXMULTIPLY: {
      complex c1, c2, c3;
      /* Note that we directly conjugate c2 before multiplication->c3=c1*c2' */
      c1.Re=     tinfo->tsdata[offset1]; c1.Im=       tinfo->tsdata[offset1+1];
      c2.Re=side_tinfo->tsdata[offset1]; c2.Im= -side_tinfo->tsdata[offset1+1];
      c3=c_mult(c1, c2);
      tinfo->tsdata[offset1]=c3.Re; tinfo->tsdata[offset1+1]=c3.Im;
      }
      break;
     case SUBTRACT_TYPE_COMPLEXDIVIDE: {
      complex c1, c2, c3;
      /* Note that we directly conjugate c2 before multiplication->c3=c1/c2' */
      c1.Re=     tinfo->tsdata[offset1]; c1.Im=       tinfo->tsdata[offset1+1];
      c2.Re=side_tinfo->tsdata[offset1]; c2.Im= -side_tinfo->tsdata[offset1+1];
      c3=c_mult(c1, c_inv(c2));
      tinfo->tsdata[offset1]=c3.Re; tinfo->tsdata[offset1+1]=c3.Im;
      }
      break;
    }
    if (local_arg->ttest) {
     /*{{{  Calculate t and p values for tinfo-side_tinfo. It is ensured that type==SUBTRACT_TYPE_SUBTRACT. */
     int const n1=(int const)(itemskip==4 ? tinfo->tsdata[offset1+3] : tinfo->nrofaverages);
     int const n2=(int const)(side_itemskip==4 ? side_tinfo->tsdata[offset2+3] : side_tinfo->nrofaverages);
     /* tsdata[offset+2] is sum(x^2), tsdata[offset+1] is sum(x) */
     /* stddevq is really n*square(sigma) */
     double const stddevq1=(tinfo->tsdata[offset1+2]-square((double)tinfo->tsdata[offset1+1])/n1);
     double const stddevq2=(side_tinfo->tsdata[offset2+2]-square((double)side_tinfo->tsdata[offset2+1])/n2);
     if (args[ARGS_LEAVE_TPARAMETERS].is_set) {
      long const N=n1+n2-1; /* The degrees of freedom for a t test against zero will be N-1 */
      /* The output will nominally have N averages, so we create
       * tweaked values that will recreate the t value for the paired
       * t-test when interpreted as sum and sumsquared and tested against zero. */
      tinfo->tsdata[offset1+1]=(tinfo->tsdata[offset1+1]/n1-side_tinfo->tsdata[offset2+1]/n2)*N;
      tinfo->tsdata[offset1+2]=((stddevq1+stddevq2)*(n1+n2)/(n1*n2))*N+square((double)tinfo->tsdata[offset1+1])/N;
      if (itemskip==4) {
       tinfo->tsdata[offset1+3]=N;
      }
     } else {
      double const stddev=sqrt((stddevq1+stddevq2)/(n1+n2-2));
      double const tval=(tinfo->tsdata[offset1+1]/n1-side_tinfo->tsdata[offset2+1]/n2)/stddev*sqrt(((double)n1*n2)/(n1+n2));
      tinfo->tsdata[offset1+1]=tval;
      tinfo->tsdata[offset1+2]=student_p(n1+n2-2, (float)fabs(tval));
     }
     /*}}}  */
    }
   }
  }
 }

 if (args[ARGS_TTEST].is_set && itemskip!=4) {
  /* Set the output nrofaverages to the necessary value needed for
   * 'calc ttest' to compute the correct values, but also to allow z score
   * computation from the t value by 'scale_by -i 1 invsqrtnrofaverages' */
  tinfo->nrofaverages=tinfo->nrofaverages+side_tinfo->nrofaverages-1;
 } else if (local_arg->type==SUBTRACT_TYPE_MEAN) {
  tinfo->nrofaverages=2;
 } else if (local_arg->type==SUBTRACT_TYPE_WMEAN) {
  tinfo->nrofaverages+=side_tinfo->nrofaverages;
 }
 return tinfo->tsdata;
}
Exemple #14
0
void polydiv (header *hd)
{	header *st=hd,*hd1,*result,*rest;
	int c1,c2,i,r,j;
	double *m1,*m2,*mr,*mh,x,l;
	complex *mc1,*mc2,*mcr,*mch,xc,lc,hc;
	interval *mi1,*mi2,*mir,*mih,xi,li,hi;
	hd1=next_param(st);
	equal_params_2(&hd,&hd1); if (error) return;
	getmatrix(hd,&r,&c1,&m1); if (r!=1) wrong_arg();
	getmatrix(hd1,&r,&c2,&m2); if (r!=1) wrong_arg();
	if (c1<c2)
	{	result=new_real(0.0,"");
		rest=(header *)newram;
		moveresult(rest,hd1);
	}
	else if (iscomplex(hd))
	{	mc1=(complex *)m1; mc2=(complex *)m2;
		result=new_cmatrix(1,c1-c2+1,""); if (error) return;
		mcr=(complex *)matrixof(result);
		rest=new_cmatrix(1,c2,""); if (error) return;
		mch=(complex *)newram;
		if (!freeram(c1*sizeof(complex)))
		{	output("Out of memory!\n"); error=190; return;
		}
		memmove((char *)mch,(char *)mc1,c1*sizeof(complex));
		c_copy(lc,mc2[c2-1]);
		if (lc[0]==0.0 && lc[1]==0.0) wrong_arg();
		for (i=c1-c2; i>=0; i--)
		{	c_div(mch[c2+i-1],lc,xc); c_copy(mcr[i],xc);
			for(j=0; j<c2; j++)
			{	c_mult(mc2[j],xc,hc);
				c_sub(mch[i+j],hc,mch[i+j]);
			}
		}
		memmove((char *)matrixof(rest),(char *)mch,c2*sizeof(complex));
	}
	else if (isinterval(hd))
	{	mi1=(interval *)m1; mi2=(interval *)m2;
		result=new_imatrix(1,c1-c2+1,""); if (error) return;
		mir=(interval *)matrixof(result);
		rest=new_imatrix(1,c2,""); if (error) return;
		mih=(complex *)newram;
		if (!freeram(c1*sizeof(complex)))
		{	output("Out of memory!\n"); error=190; return;
		}
		memmove((char *)mih,(char *)mi1,c1*sizeof(interval));
		i_copy(li,mi2[c2-1]);
		if (li[0]<=0.0 && li[1]>=0.0) wrong_arg();
		for (i=c1-c2; i>=0; i--)
		{	i_div(mih[c2+i-1],li,xi); c_copy(mir[i],xi);
			for(j=0; j<c2; j++)
			{	i_mult(mi2[j],xi,hi);
				i_sub(mih[i+j],hi,mih[i+j]);
			}
		}
		memmove((char *)matrixof(rest),(char *)mih,c2*sizeof(interval));
	}
	else if (isreal(hd))
	{	result=new_matrix(1,c1-c2+1,""); if (error) return;
		mr=matrixof(result);
		rest=new_matrix(1,c2,""); if (error) return;
		mh=(double *)newram;
		if (!freeram(c1*sizeof(double)))
		{	output("Out of memory!\n"); error=190; return;
		}
		memmove((char *)mh,(char *)m1,c1*sizeof(double));
		l=m2[c2-1];
		if (l==0.0) wrong_arg();
		for (i=c1-c2; i>=0; i--)
		{	x=mh[c2+i-1]/l; mr[i]=x;
			for(j=0; j<c2; j++) mh[i+j]-=m2[j]*x;
		}
		memmove((char *)matrixof(rest),(char *)mh,c2*sizeof(double));
	}
	else wrong_arg();
	moveresult(st,result);
	moveresult(nextof(st),rest);
}
int main(int argc, char** argv) {
  //Precompute FFT coefficients
  Wkn_fft = precompute_fft_coefficients();
  Wkn_ifft = precompute_ifft_coefficients();
  
  // Declare local variables
  int i, j, n;

  // Read in data
  // 1. allocate buffer space for the data. Holds Nx * Ny * Nf complex numbers.
  // 2. pass the filename and buffer to read_data which will read the file
  //    into the buffer.
  printf("Reading Data ...\n");
  tick();
  complex* s = (complex*)safe_malloc(Nx * Ny * Nf * sizeof(complex),
                         "Failed to allocate memory for radar data.");  
  read_data(s, "scene_4.dat");
  tock();

  // Perform a single 2D FFT for each frequency
  // Each element s[i,j,n] is located at s[i * Ny * Nf + j * Nf + n]
  // Thus x-stride = Ny*Nf, y-stride = Nf, and z-stride = 1
  // and each xy plane starts at s + 0 * Ny * Nf + 0 * Nf + n
  printf("Performing FFT\n");
  tick();
  for(n=0; n<Nf; n++)
    fft_2d(s + n, Nx, Ny, Ny*Nf, Nf);
  tock();

  // Multiply each element in the frequency-domain signal by the
  // downward continuation phase operator.
  // 1. for each element (i,j,n) in the signal matrix
  //      i in 0 ... Nx, j in 0 ... Ny, n in 0 ... Nf
  // 2.   compute kx, ky, and k
  //        kx = 2*pi/Dx * i/Nx          if i < Nx/2,
  //             2*pi/Dx * (i-Nx)/Nx     otherwise
  //        ky = 2*pi/Dy * j/Ny          if j < Ny/2,
  //             2*pi/Dy * (j-Ny)/Ny     otherwise
  //        w  = 2*pi*(f0 + n*Df)
  //        k  = w/c
  //
  // 3.   compute kz
  //        kz = sqrt(4 * k^2 - kx^2 - ky^2 )
  // 4.   compute the phase delay
  //        phi = exp(j * kz * z0)
  // 5.   multiply the signal with the phase delay
  //        where s(i,j,k) = s[i * Ny * Nf + j * Nf + n]
  printf("Performing Downward Continuation.\n");
  tick();
  for(i=0; i<Nx; i++)
    for(j=0; j<Ny; j++)
      for(n=0; n<Nf; n++){
        float kx = i < Nx/2 ?
          2*pi/Dx * i/Nx :
          2*pi/Dx * (i - Nx)/Nx;
        float ky = j < Ny/2 ?
          2*pi/Dy * j/Ny :
          2*pi/Dy * (j - Ny)/Ny;
        
        float w = 2*pi*(f0 + n*Df);
        float k = w/c_speed;
        float kz = sqrt(4*k*k - kx*kx - ky*ky);
        
        complex phi = c_jexp(kz * z0);
        s[i * Ny * Nf + j * Nf + n] = c_mult(s[i * Ny * Nf + j * Nf + n], phi);        
      }
  tock();

  // Calculate the range of the Stolt interpolation indices.
  // The minimum angular frequency, w_min = 2*pi * f0
  // The maximum angular frequency, w_max = 2*pi * (f0 + (N - 1)*Df)
  // From which the
  //   minimum wavenumber, k_min = w_min / c
  //   maximum wavenumber, k_max = w_max / c
  // The maximum wavenumber in the x direction, kx_max = 2*pi/Dx * 0.5 * (Nx-1)/Nx
  // The maximum wavenumber in the y direction, ky_max = 2*pi/Dy * 0.5 * (Ny-1)/Ny
  // The minimum wavenumbers in the x and y direction are assumed to be 0
  // From which the
  //   minimum wavenumber in the z direction, kz_min = sqrt(4*k_min^2 - kx_max^2 - ky_max^2)
  //   maximum wavenumber in the z direction, kz_max = sqrt(4*k_max^2 - 0 - 0)
  float w_min = 2*pi * f0;
  float w_max = 2*pi * (f0 + (Nf - 1)*Df);
  float k_min = w_min / c_speed;
  float k_max = w_max / c_speed;
  float kx_max = 2*pi/Dx * 0.5 * (Nx-1)/Nx;
  float ky_max = 2*pi/Dy * 0.5 * (Ny-1)/Ny;
  float kz_min = sqrt(4*k_min*k_min - kx_max*kx_max - ky_max*ky_max);
  float kz_max = sqrt(4*k_max*k_max);

  // Perform Stolt Interpolation
  // 1. for each step in the x direction, i in 0 ... Nx
  //    and each step in the y direction, j in 0 ... Ny
  // 2.   compute kx, and ky as per step 2. above
  // 3.   create float buffer of size Nf for storing the interpolation indices, n_interp
  // 4.   for each step in frequency, n in 0 ... Nf
  //         compute kz = kz_min + (kz_max - kz_min) * n/(Nf - 1)
  // 4.      compute desired k = 0.5 * sqrt(kx^2 + ky^2 + kz^2)
  // 5.      which corresponds to the interpolated array element
  //            n_interp[n] = (c*k/(2*pi) - f0)/Df
  // 6.   resample this line in s on interpolated indices n_interp
  //         s[i,j,n] is at s[i * Ny * Nf + j * Nf + n] thus this line
  //           starts at s + i * Ny * Nf + j * Nf + 0, has length Nf, and has stride 1
  printf("Performing Stolt Interpolation.\n");
  tick();
  for(i=0; i<Nx; i++)
    for(j=0; j<Ny; j++){
      float kx = i < Nx/2 ?
        2*pi/Dx * i/Nx :
        2*pi/Dx * (i - Nx)/Nx;
      float ky = j < Ny/2 ?
        2*pi/Dy * j/Ny :
        2*pi/Dy * (j - Ny)/Ny;

      float n_interp[Nf];
      for(n=0; n<Nf; n++){
        float kz = kz_min + (kz_max - kz_min) * n/(Nf - 1);
        float k = 0.5 * sqrt(kx*kx + ky*ky + kz*kz);
        n_interp[n] = (c_speed*k/(2*pi) - f0)/Df;
      }
      
      resample_1d(s + i*Ny*Nf + j*Nf, Nf, 1, n_interp);
    }
  tock();

  // Perform a 3D IFFT on the signal
  // Each element s[i,j,n] is located at s[i * Ny * Nf + j * Nf + n]
  // Thus x-stride = Ny*Nf, y-stride = Nf, and z-stride = 1
  printf("Performing IFFT.\n");
  tick();
  ifft_3d(s, Nx, Ny, Nf, Ny*Nf, Nf, 1);
  tock();

  // End the simulation by writing out the computed signal and write it out to a file.
  // Pass the computed matrix and a output filename to write_data()
  printf("Writing data ...\n");
  tick();
  write_data(s, "scene_4.out");
  tock();
  printf("Done.\n");

  // Free all the temporary memory
  free(s);
}
Exemple #16
0
void complex_test()
{
	cComplex *one, *two, *target;
	time_t start, finish;
	int num_loops, i, total_time;

	num_loops = 50000000;

	// allocate memory for two cComplex structures
	one = (cComplex *)malloc(sizeof(cComplex));
	if(one == NULL)
		printf("\nError allocating memory(%d)", __LINE__);
	
	two = (cComplex *)malloc(sizeof(cComplex));
	if(two == NULL)
		printf("\nError allocating memory(%d)", __LINE__);

	target = (cComplex *)malloc(sizeof(cComplex));
	if(target == NULL)
		printf("\nError allocating memory(%d)", __LINE__);

	printf("\nChecking c_add() function: (ans: 1 + 1i)");
	one->re = 1;
	one->im = 0;
	two->re = 0;
	two->im = 1;
	c_print_t(one);
	c_print_t(two);
	c_add(one, two, target);
	c_print_t(target);

	printf("\nChecking c_mult() function: (ans: -8 + 12i");
	one->re = 2;
	one->im = 2;
	two->re = 1;
	two->im = 5;
	c_print_t(one);
	c_print_t(two);
	c_mult(one, two, target);
	c_print_t(target);

	printf("\nChecking c_exp_complex() function: (ans: 148.4 + 2.59i");
	one->re = 5;
	one->im = 1;
	c_print_t(one);
	c_exp_complex(one, target);
	c_print_t(target);

	printf("\nChecking speed of %d loops each of c_add(), c_mult() and c_exp_complex()", num_loops);

	start = clock();
	for(i = 0; i < num_loops; i++)
	{
		c_add(one, two, target);
	}
	finish = clock();
	
	total_time = (int)(finish - start);

	printf("\nTotal time for %d c_add() calls: %d ms", num_loops, finish-start);

	start = clock();
	for(i = 0; i < num_loops; i++)
	{
		c_mult(one, two, target);
	}
	finish = clock();
	
	total_time += (int)(finish - start);

	printf("\nTotal time for %d c_mult() calls: %d ms", num_loops, finish-start);

	start = clock();
	for(i = 0; i < num_loops; i++)
	{
		c_exp_complex(one, target);
	}
	finish = clock();
	
	total_time += (int)(finish - start);

	printf("\nTotal time for %d c_exp_complex() calls: %d ms", num_loops, finish-start);

	printf("\nTotal time for %d loops each of c_add(), c_mult(), and c_exp_complex(): %d ms", 
			num_loops, total_time);

}