Ejemplo n.º 1
0
/***************************************************************************************
Deconvolve the B-spline basis functions from the image volume
	vol - a handle for the volume to deconvolve
	c - the coefficients (arising from the deconvolution)
	d - the spline degree
	splinc0, splinc1, splinc2	- functions for 1D deconvolutions
*/
static int vol_coeffs(MAPTYPE *vol, double c[], int d[], void (*splinc[])())
{
	double	p[4], *cp;
	int	np;
	int	i, j, k, n;
	double f[10240];

	/* Check that dimensions don't exceed size of f */
	if (vol->dim[1]>10240 ||vol->dim[2]>10240)
		return(1);

	/* Do a straight copy */
	cp = c;
	for(k=0; k<vol->dim[2]; k++)
	{
		double dk = k+1;
		for(j=0; j<vol->dim[1]; j++)
		{
			double dj = j+1;
			for(i=0;i<vol->dim[0];i++, cp++)
			{
				double di = i+1;
				resample(1,vol,cp,&di,&dj,&dk,0, 0.0);

				/* Not sure how best to handle NaNs */
				if (!finite(*cp)) *cp = 0.0;
			}
		}
	}

	/* Deconvolve along the fastest dimension (X) */
	if (d[0]>1 && vol->dim[0]>1)
	{
		if (get_poles(d[0], &np, p)) return(1);
		for(k=0; k<vol->dim[2]; k++)
		{
			double dk = k+1;
			for(j=0; j<vol->dim[1]; j++)
			{
				cp = &c[vol->dim[0]*(j+vol->dim[1]*k)];
				splinc[0](cp, vol->dim[0], p, np);
			}
		}
	}

	/* Deconvolve along the middle dimension (Y) */
	if (d[1]>1 && vol->dim[1]>1)
	{
		if (get_poles(d[1], &np, p)) return(1);
		n =vol->dim[0];
		for(k=0; k<vol->dim[2]; k++)
		{
			for(i=0;i<vol->dim[0];i++)
			{
				cp = &c[i+vol->dim[0]*vol->dim[1]*k];
				for(j=0; j<vol->dim[1]; j++, cp+=n)
					f[j] = *cp;
				splinc[1](f, vol->dim[1], p, np);
				cp = &c[i+vol->dim[0]*vol->dim[1]*k];
				for(j=0; j<vol->dim[1]; j++, cp+=n)
					*cp = f[j];
			}
		}
	}

	/* Deconvolve along the slowest dimension (Z) */
	if (d[2]>1 && vol->dim[2]>1)
	{
		if (get_poles(d[2], &np, p)) return(1);
		n = vol->dim[0]*vol->dim[1];
		for(j=0; j<vol->dim[1]; j++)
		{
			for(i=0;i<vol->dim[0];i++)
			{
				cp = &c[i+vol->dim[0]*j];
				for(k=0; k<vol->dim[2]; k++, cp+=n)
					f[k] = *cp;
				splinc[2](f, vol->dim[2], p, np);
				cp = &c[i+vol->dim[0]*j];
				for(k=0; k<vol->dim[2]; k++, cp+=n)
					*cp = f[k];
			}
		}
	}
	return(0);
}
Ejemplo n.º 2
0
  void
  processArray(bool aAverageMode = false)
  {
    uint32_t nNotNans = 0;

    if (mScramble)
    {
      boost::uniform_int<uint32_t> ui(0, nGenes - 1);
      for (uint32_t k = 0; k < nGenes; k++)
      {
        double t = mBuf[k];
        uint32_t h = ui(mRand);
        
        mBuf[k] = mBuf[h];
        mBuf[h] = t;
      }
    }

    for (uint32_t i = 0; i < nGenes; i++)
    {
      mInvRanks[i] = i;
      nNotNans += !!finite(mBuf[i]);
    }

    double rankInflationFactor = (nGenes + 0.0) / nNotNans;

    // Sort indices by value, with NaNs at the top.
    std::sort(mInvRanks, mInvRanks + nGenes,
              (bll::var(mBuf)[bll::_1] < bll::var(mBuf)[bll::_2]) ||
              (bll::bind(finite, bll::var(mBuf)[bll::_1]) &&
               !bll::bind(finite, bll::var(mBuf)[bll::_2])));
    
    uint32_t i;
    if (aAverageMode)
    {
      for (i = 0; i < nGenes && finite(mBuf[mInvRanks[i]]); i++)
      {
        mRankAvgs[i] += mBuf[mInvRanks[i]];
        mRankCounts[i]++;
      }
    }
    else
    {
      if (mQuantileNormalisation)
      {
        for (i = 0; i < nGenes && finite(mBuf[mInvRanks[i]]); i++)
          // We could put code in here to deal with tied ranks by putting in median
          // ranks, but I doubt it would make enough difference to justify it.
          mRanks[mInvRanks[i]] = mRankAvgs[i];
      }
      else
      {
        for (i = 0; i < nGenes && finite(mBuf[mInvRanks[i]]); i++)
          // We could put code in here to deal with tied ranks by putting in median
          // ranks, but I doubt it would make enough difference to justify it.
          mRanks[mInvRanks[i]] = i * rankInflationFactor;
      }

      for (; i < nGenes; i++)
        mRanks[mInvRanks[i]] = std::numeric_limits<double>::quiet_NaN();

      fwrite(mRanks, sizeof(double), nGenes, mOutputFile);
    }
  }
Ejemplo n.º 3
0
/* Split plnode along plane. We know that plane really intersects
 * plnode->poly. We also know that plnode->poly is planar and convex.
 *
 * Given this assumptions we know that plnode->poly has to be split
 * into exactly two pieces. 
 */
static inline void SplitPolyNode(PolyListNode *plnode,
				 PolyListNode **front, PolyListNode **back,
				 EdgeIntersection edges[2],
				 struct obstack *scratch)
{
  const void **tagged_app = plnode->tagged_app;
  Poly *poly = plnode->poly, savedp;
  VARARRAY(savedv, Vertex *, poly->n_vertices);
  Vertex *v0, *v1, **vpos;
  int istart[2], iend[2], i, nv[2];
  Vertex *vstart[2], *vend[2];

#if BSPTREE_STATS
  ++n_tree_polys;
#endif

  vstart[0] = vstart[1] = vend[0] = vend[1] = NULL;
  istart[0] = istart[1] = iend[0] = iend[1] = -1;

  /* first point of intersection */
  if (fzero(edges[0].scp[0])) {
    v0 = poly->v[edges[0].v[0]];
    if (fpos(edges[0].scp[1])) {
      istart[0] = edges[0].v[0];
      iend[1]   = edges[0].v[0];
    } else {
      istart[1] = edges[0].v[0];
      iend[0]   = edges[0].v[0]; 
    }
  } else if (fzero(edges[0].scp[1])) {
    v0 = poly->v[edges[0].v[1]];
    if (fpos(edges[0].scp[0])) {
      istart[1] = edges[0].v[1];
      iend[0]   = edges[0].v[1];
    } else {
      istart[0] = edges[0].v[1];
      iend[1]   = edges[0].v[1]; 
    }
  } else {
    HPt3Coord mu0, mu1;
    Vertex *V0 = poly->v[edges[0].v[0]];
    Vertex *V1 = poly->v[edges[0].v[1]];
    
    v0 = obstack_alloc(scratch, sizeof(Vertex));
    mu0 = edges[0].scp[1]/(edges[0].scp[1]-edges[0].scp[0]);
#if 0
    mu1 = edges[0].scp[0]/(edges[0].scp[0]-edges[0].scp[1]);
#else
    mu1 = 1.0 - mu0;
#endif
    /* Use denormalized variant; otherwise textures may come out wrong
     * because the homogeneous divisor is used for perspective
     * corrections.
     */
    if (poly->flags & VERT_ST) {
      v0->st.s = mu0 * V0->st.s + mu1 * V1->st.s;
      v0->st.t = mu0 * V0->st.t + mu1 * V1->st.t;
      HPt3LinSumDenorm(mu0, &V0->pt, mu1, &V1->pt, &v0->pt);
    } else {
      HPt3LinSum(mu0, &V0->pt, mu1, &V1->pt, &v0->pt);
    } 
    if (!finite(v0->pt.x + v0->pt.y + v0->pt.z)){
      abort();
    }
    if (poly->flags & VERT_C) {
      CoLinSum(mu0, &V0->vcol, mu1, &V1->vcol, &v0->vcol);
    }
    if (true || (poly->flags & VERT_N)) {
      /* The averaged vertex normals do not have an orientation, so
       * try to orient them w.r.t. the polygon normal before computing
       * the linear combination.
       */
      if (Pt3Dot(&V0->vn, &poly->pn)*Pt3Dot(&V1->vn, &poly->pn) < 0) {
	Pt3Comb(-mu0, &V0->vn, mu1, &V1->vn, &v0->vn);
      } else {
	Pt3Comb(mu0, &V0->vn, mu1, &V1->vn, &v0->vn);
      }
      Pt3Unit(&v0->vn);
    }

    if (fpos(edges[0].scp[0])) {
      vstart[1] = vend[0] = v0;
      istart[1] = edges[0].v[1];
      iend[0]   = edges[0].v[0];
    } else {
      vstart[0] = vend[1] = v0;
      istart[0] = edges[0].v[1];
      iend[1]   = edges[0].v[0];
    }
  }

  /* second point of intersection */
  if (fzero(edges[1].scp[0])) {
    v1 = poly->v[edges[1].v[0]];
    if (fpos(edges[1].scp[1])) {
      istart[0] = edges[1].v[0];
      iend[1]   = edges[1].v[0];
    } else {
      istart[1] = edges[1].v[0];
      iend[0]   = edges[1].v[0]; 
    }
  } else if (fzero(edges[1].scp[1])) {
    v1 = poly->v[edges[1].v[1]];
    if (fpos(edges[1].scp[0])) {
      istart[1] = edges[1].v[1];
      iend[0]   = edges[1].v[1];
    } else {
      istart[0] = edges[1].v[1];
      iend[1]   = edges[1].v[1]; 
    }
  } else {
    HPt3Coord mu0, mu1;
    Vertex *V0 = poly->v[edges[1].v[0]];
    Vertex *V1 = poly->v[edges[1].v[1]];
    
    v1 = obstack_alloc(scratch, sizeof(Vertex));
    mu0 = edges[1].scp[1]/(edges[1].scp[1]-edges[1].scp[0]);
#if 0
    mu1 = edges[1].scp[0]/(edges[1].scp[0]-edges[1].scp[1]);
#else
    mu1 = 1.0 - mu0;
#endif
    if (poly->flags & VERT_ST) {
      v1->st.s = mu0 * V0->st.s + mu1 * V1->st.s;
      v1->st.t = mu0 * V0->st.t + mu1 * V1->st.t;
      HPt3LinSumDenorm(mu0, &V0->pt, mu1, &V1->pt, &v1->pt);
    } else {
      HPt3LinSum(mu0, &V0->pt, mu1, &V1->pt, &v1->pt);
    }
    if (!finite(v1->pt.x + v1->pt.y + v1->pt.z))
      abort();
    if (poly->flags & VERT_C) {
      CoLinSum(mu0, &V0->vcol, mu1, &V1->vcol, &v1->vcol);
    }
    if (true || (poly->flags & VERT_N)) {
      if (Pt3Dot(&V0->vn, &poly->pn)*Pt3Dot(&V1->vn, &poly->pn) < 0) {
	Pt3Comb(-mu0, &V0->vn, mu1, &V1->vn, &v1->vn);
      } else {
	Pt3Comb(mu0, &V0->vn, mu1, &V1->vn, &v1->vn);
      }
      Pt3Unit(&v1->vn);
    }

    if (fpos(edges[1].scp[0])) {
      vstart[1] = vend[0] = v1;
      istart[1] = edges[1].v[1];
      iend[0]   = edges[1].v[0];
    } else {
      vstart[0] = vend[1] = v1;
      istart[0] = edges[1].v[1];
      iend[1]   = edges[1].v[0];
    }
  }

  ListPush(*front, plnode);
  ListPush(*back, new_poly_list_node(tagged_app, scratch));

  if ((poly->flags & POLY_NONFLAT)) {
    if (!(*front)->pn) {
      /* Compute the normal on the parent element to avoid numerical
       * instabilities on increasingly degenerated polygons.
       */
      (*front)->pn = obstack_alloc(scratch, sizeof(Point3));
      PolyNormal(poly, (*front)->pn,
		 true /* 4d */, false /* evert */, NULL, NULL);
    }
    (*back)->pn = (*front)->pn;
  }

  for (i = 0; i < 2; i++) {
    nv[i] = iend[i] - istart[i] + 1;
    if (nv[i] < 0) {
      nv[i] += poly->n_vertices;
    }
    nv[i] += (vstart[i] != NULL) + (vend[i] != NULL);
  }

  if (poly->flags & POLY_SCRATCH) {

    savedp = *poly;
    memcpy(savedv, poly->v, poly->n_vertices*sizeof(Vertex *));

    if (nv[0] <= poly->n_vertices) {
      poly->n_vertices = nv[0];
      (*front)->poly = poly;
      (*back)->poly  = new_poly(nv[1], NULL, scratch);
    } else {
      if (nv[1] > poly->n_vertices) {
	abort();
      }
      poly->n_vertices = nv[1];
      (*back)->poly = poly;
      (*front)->poly  = new_poly(nv[0], NULL, scratch);
    }
    
    /* Attention: gcc had problems with this code snippet with
     * -fstrict-aliasing, the "#if 1" stuff seems to work. In the
     * "#else" version gcc somehow lost the "savedp.v = savedv"
     * assignment. I think this is a compiler bug.
     */
    poly = &savedp;
#if 1
    poly->v = savedv;
#else
    savedp.v = savedv;
#endif
  } else {
    (*front)->poly  = new_poly(nv[0], NULL, scratch);
    (*back)->poly  = new_poly(nv[1], NULL, scratch);
  }

  for (i = 0; i < 2; i++) {
    PolyListNode *half = (i == 0) ? *front : *back;
    int j;

    vpos = half->poly->v;
    if (vstart[i] != NULL) {
      *vpos++ = vstart[i];
    }
    if (istart[i] <= iend[i]) {
      for (j = istart[i]; j <= iend[i] && j < poly->n_vertices; j++) {
	*vpos++ = poly->v[j];
      }
    } else {
      for (j = istart[i]; j < poly->n_vertices; j++) {
	*vpos++ = poly->v[j];
      }
      for (j = 0; j <= iend[i]; j++) {
	*vpos++ = poly->v[j];
      }
    }
    if (vend[i] != NULL) {
      *vpos++ = vend[i];
    }
    half->poly->pcol  = poly->pcol;
    half->poly->pn    = poly->pn;
    half->poly->flags = poly->flags|POLY_SCRATCH;

    check_poly(half->poly);
  }
}
Ejemplo n.º 4
0
void Linearizer::process_quad(int iv0, int iv1, int iv2, int iv3, int level,
                              scalar* val, double* phx, double* phy, int* idx)
{
  double midval[3][5];

  // try not to split through the vertex with the largest value
  int a = (verts[iv0][2] > verts[iv1][2]) ? iv0 : iv1;
  int b = (verts[iv2][2] > verts[iv3][2]) ? iv2 : iv3;
  a = (verts[a][2] > verts[b][2]) ? a : b;
  int flip = (a == iv1 || a == iv3) ? 1 : 0;

  if (level < LIN_MAX_LEVEL)
  {
    int i;
    if (!(level & 1)) // this is an optimization: do the following only every other time
    {
      // obtain solution values
      sln->set_quad_order(1, item);
      val = sln->get_values(ia, ib);
      if (auto_max)
        for (i = 0; i < lin_np_quad[1]; i++) {
          double v = getval(i);
          if (finite(v) && fabs(v) > max) max = fabs(v);
        }

      // obtain physical element coordinates
      if (curved || disp)
      {
        RefMap* refmap = sln->get_refmap();
        phx = refmap->get_phys_x(1);
        phy = refmap->get_phys_y(1);

        if (disp)
        {
          xdisp->force_transform(sln);
          ydisp->force_transform(sln);
          xdisp->set_quad_order(1, FN_VAL);
          ydisp->set_quad_order(1, FN_VAL);
          scalar* dx = xdisp->get_fn_values();
          scalar* dy = ydisp->get_fn_values();
          for (i = 0; i < lin_np_quad[1]; i++) {
            phx[i] += dmult*realpart(dx[i]);
            phy[i] += dmult*realpart(dy[i]);
          }
        }
      }
      idx = quad_indices[0];
    }

    // obtain linearized values and coordinates at the midpoints
    for (i = 0; i < 3; i++)
    {
      midval[i][0] = (verts[iv0][i] + verts[iv1][i]) * 0.5;
      midval[i][1] = (verts[iv1][i] + verts[iv2][i]) * 0.5;
      midval[i][2] = (verts[iv2][i] + verts[iv3][i]) * 0.5;
      midval[i][3] = (verts[iv3][i] + verts[iv0][i]) * 0.5;
      midval[i][4] = (midval[i][0]  + midval[i][2])  * 0.5;
    };

    // the value of the middle point is not the average of the four vertex values, since quad == 2 triangles
    midval[2][4] = flip ? (verts[iv0][2] + verts[iv2][2]) * 0.5 : (verts[iv1][2] + verts[iv3][2]) * 0.5;


    // determine whether or not to split the element
    int split;
    if (eps >= 1.0)
    {
      // if eps > 1, the user wants a fixed number of refinements (no adaptivity)
      split = (level < eps) ? 3 : 0;
    }
    else
    {
      if (!auto_max && fabs(verts[iv0][2]) > max && fabs(verts[iv1][2]) > max
                         && fabs(verts[iv2][2]) > max && fabs(verts[iv3][2]) > max)
      {
        // do not split if the whole quad is above the specified maximum value
        split = 0;
      }
      else
      {
        // calculate the approximate error of linearizing the normalized solution
        double herr = fabs(getval(idx[1]) - midval[2][1]) + fabs(getval(idx[3]) - midval[2][3]);
        double verr = fabs(getval(idx[0]) - midval[2][0]) + fabs(getval(idx[2]) - midval[2][2]);
        double err  = fabs(getval(idx[4]) - midval[2][4]) + herr + verr;
        split = (!finite(err) || err > max*4*eps) ? 3 : 0;

        // decide whether to split horizontally or vertically only
        if (level > 0 && split)
          if (herr > 5*verr)
            split = 1; // h-split
          else if (verr > 5*herr)
            split = 2; // v-split
      }

      // also decide whether to split because of the curvature
      if (split != 3 && (curved || disp))
      {
        double cm2 = sqr(cmax*5e-4);
        if (sqr(phx[idx[1]] - midval[0][1]) + sqr(phy[idx[1]] - midval[1][1]) > cm2 ||
            sqr(phx[idx[3]] - midval[0][3]) + sqr(phy[idx[3]] - midval[1][3]) > cm2) split |= 1;
        if (sqr(phx[idx[0]] - midval[0][0]) + sqr(phy[idx[0]] - midval[1][0]) > cm2 ||
            sqr(phx[idx[2]] - midval[0][2]) + sqr(phy[idx[2]] - midval[1][2]) > cm2) split |= 2;

        /*for (i = 0; i < 5; i++)
          if (sqr(phx[idx[i]] - midval[0][i]) + sqr(phy[idx[i]] - midval[1][i]) > sqr(cmax*1e-3))
            { split = 1; break; }*/
      }

      // do extra tests at level 0, so as not to miss some functions with zero error at edge midpoints
      if (level == 0 && !split)
      {
        split = ((fabs(getval(13) - 0.5*(midval[2][0] + midval[2][1])) +
                  fabs(getval(17) - 0.5*(midval[2][1] + midval[2][2])) +
                  fabs(getval(20) - 0.5*(midval[2][2] + midval[2][3])) +
                  fabs(getval(9)  - 0.5*(midval[2][3] + midval[2][0]))) > max*4*eps) ? 3 : 0;
      }
    }

    // split the quad if the error is too large, otherwise produce two linear triangles
    if (split)
    {
      if (curved || disp)
        for (i = 0; i < 5; i++) {
          midval[0][i] = phx[idx[i]];
          midval[1][i] = phy[idx[i]];
        }

      // obtain mid-edge and mid-element vertices
      int mid0, mid1, mid2, mid3, mid4;
      if (split != 1) mid0 = get_vertex(iv0,  iv1,  midval[0][0], midval[1][0], getval(idx[0]));
      if (split != 2) mid1 = get_vertex(iv1,  iv2,  midval[0][1], midval[1][1], getval(idx[1]));
      if (split != 1) mid2 = get_vertex(iv2,  iv3,  midval[0][2], midval[1][2], getval(idx[2]));
      if (split != 2) mid3 = get_vertex(iv3,  iv0,  midval[0][3], midval[1][3], getval(idx[3]));
      if (split == 3) mid4 = get_vertex(mid0, mid2, midval[0][4], midval[1][4], getval(idx[4]));

      // recur to sub-elements
      if (split == 3)
      {
        sln->push_transform(0);  process_quad(iv0, mid0, mid4, mid3, level+1, val, phx, phy, quad_indices[1]);  sln->pop_transform();
        sln->push_transform(1);  process_quad(mid0, iv1, mid1, mid4, level+1, val, phx, phy, quad_indices[2]);  sln->pop_transform();
        sln->push_transform(2);  process_quad(mid4, mid1, iv2, mid2, level+1, val, phx, phy, quad_indices[3]);  sln->pop_transform();
        sln->push_transform(3);  process_quad(mid3, mid4, mid2, iv3, level+1, val, phx, phy, quad_indices[4]);  sln->pop_transform();
      }
      else if (split == 1) // h-split
      {
        sln->push_transform(4);  process_quad(iv0, iv1, mid1, mid3, level+1, val, phx, phy, quad_indices[5]);  sln->pop_transform();
        sln->push_transform(5);  process_quad(mid3, mid1, iv2, iv3, level+1, val, phx, phy, quad_indices[6]);  sln->pop_transform();
      }
      else // v-split
      {
        sln->push_transform(6);  process_quad(iv0, mid0, mid2, iv3, level+1, val, phx, phy, quad_indices[7]);  sln->pop_transform();
        sln->push_transform(7);  process_quad(mid0, iv1, iv2, mid2, level+1, val, phx, phy, quad_indices[8]);  sln->pop_transform();
      }
      return;
    }
  }

  // output two linear triangles,
  if (!flip)
  {
    add_triangle(iv3, iv0, iv1);
    add_triangle(iv1, iv2, iv3);
  }
  else
  {
    add_triangle(iv0, iv1, iv2);
    add_triangle(iv2, iv3, iv0);
  }
}
Ejemplo n.º 5
0
TEST(math, finite) {
  ASSERT_TRUE(finite(123.0));
  ASSERT_FALSE(finite(HUGE_VAL));
}
Ejemplo n.º 6
0
/*++
Function:
    pow

See MSDN.
--*/
PALIMPORT double __cdecl PAL_pow(double x, double y)
{
    double ret;

    PERF_ENTRY(pow);
    ENTRY("pow (x=%f, y=%f)\n", x, y);
#if !HAVE_COMPATIBLE_POW
    if (y == 1.0 / 0.0 && !isnan(x))    // +Inf
    {
        if (x == 1.0 || x == -1.0)
        {
            ret = 0.0 / 0.0;    // NaN
        }
        else if (x > -1.0 && x < 1.0)
        {
            ret = 0.0;
        }
        else
        {
            ret = 1.0 / 0.0;    // +Inf
        }
    }
    else if (y == -1.0 / 0.0 && !isnan(x))   // -Inf
    {
        if (x == 1.0 || x == -1.0)
        {
            ret = 0.0 / 0.0;    // NaN
        }
        else if (x > -1.0 && x < 1.0)
        {
            ret = 1.0 / 0.0;    // +Inf
        }
        else
        {
            ret = 0.0;
        }
    }
    else if (x == 0.0 && y < 0.0)
    {
        ret = 1.0 / 0.0;    // +Inf
    }
    else
#endif  // !HAVE_COMPATIBLE_POW
    if (y == 0.0 && isnan(x))
    {
        // Windows returns NaN for pow(NaN, 0), but POSIX specifies
        // a return value of 1 for that case.  We need to return
        // the same result as Windows.
        ret = 0.0 / 0.0;    // NaN
    }
    else
    {
        ret = pow(x, y);
    }
#if !HAVE_VALID_NEGATIVE_INF_POW
    if (ret == 1.0 / 0.0 && x < 0 && finite(x) && ceil(y/2) != floor(y/2))
    {
        ret = -1.0 / 0.0;   // -Inf
    }
#endif  // !HAVE_VALID_NEGATIVE_INF_POW
#if !HAVE_VALID_POSITIVE_INF_POW
    /*
     * The even/odd test in the if (this one and the one above) used to be ((long long) y % 2 == 0)
     * on SPARC (long long) y for large y (>2**63) is always 0x7fffffff7fffffff, which
     * is an odd number, so the test ((long long) y % 2 == 0) will always fail for
     * large y. Since large double numbers are always even (e.g., the representation of
     * 1E20+1 is the same as that of 1E20, the last “+1” is too insignificant to be part
     * of the representation), this test will always return the wrong result for large y.
     * 
     * The (ceil(y/2) == floor(y/2)) test is slower, but more robust.
     */
    if (ret == -1.0 / 0.0 && x < 0 && finite(x) && ceil(y/2) == floor(y/2))
    {
        ret = 1.0 / 0.0;   // +Inf
    }
#endif  // !HAVE_VALID_POSITIVE_INF_POW
    LOGEXIT("pow returns double %f\n", ret);
    PERF_EXIT(pow);
    return ret;
}
Ejemplo n.º 7
0
int main(int argc, char** argv)
{
  double power;
  double A0, lA0;
  double Zau, Za, Zaa;
  double ZaInf, ZaaInf;
  double Ta, Taa;
  double lKa;
  double A;
  double openEnthalpy, openEntropy;

  char c, gotData;
  int count;
  char *name, *buffer, *prefix;
  FILE *aFile, *aaFile, *outFile;
  int ignore[2];
  int zInfinity;
  time_t now;

  gotData = 0;
  name = prefix = NULL;
  ignore[0] = ignore[1] = 0;
  openEnthalpy = HUGE_VAL;
  openEntropy = -HUGE_VAL;
  power = 1.0;
  zInfinity = 0;

  /* initializations below are unnecessary but prevent compiler warnings */
  lA0 = A0 = 0.0;
  aFile = aaFile = NULL;

  while ((count = getopt_long(argc, argv, "VhA:x:H:S:b:Yo:", OPTIONS, NULL)) != -1)
    if (count == 'V')
      version("concentration-same");
    else if (count == 'h' || count == '?')
      {
	puts("Usage: concentration-same [options] prefix");
	puts("");
	puts("Options:");
	puts("-V, --version");
	puts("-h, --help");
	puts("-A, --A0=<total A>");
	puts("-x, --exclude=(A|AA)");
	puts("-H, --enthalpy=<enthalpy for unfolded strands> (defaults to +infinity)");
	puts("-S, --entropy=<entropy for unfolded strands> (defaults to -infinity)");
	puts("-b, --power=<exponent for unfolded strands> (defaults to 1)");
	puts("-o, --output=<prefix>");
	puts("-Y, --infinity");
	puts("");
	puts("Report bugs to " PACKAGE_BUGREPORT);
	return EXIT_SUCCESS;
      }
    else if (count == 'A')
      {
	A0 = atof(optarg);
	lA0 = log(A0);
	gotData |= 1;
      }
    else if (count == 'x')
      {
	if (!strcmp(optarg, "A"))
	  ignore[0] = 1;
	else if (!strcmp(optarg, "AA"))
	  ignore[1] = 1;
      }
    else if (count == 'H')
      openEnthalpy = atof(optarg);
    else if (count == 'S')
      openEntropy = atof(optarg) / 1000;
    else if (count == 'b')
      power = atof(optarg);
    else if (count == 'Y')
      ++zInfinity;
    else if (count == 'o')
      prefix = optarg;

  if (gotData != 1 || optind >= argc)
    {
      fputs("Error: data not specified\nRun 'concentration-same -h' for help\n", stderr);
      return EXIT_FAILURE;
    }

  if (ignore[0] && ignore[1])
    {
      fputs("Error: can't ignore everything\n", stderr);
      return EXIT_FAILURE;
    }

  name = argv[optind];
  if (!strcmp(name + strlen(name) - 4, ".seq"))
    name[strlen(name) - 4] = 0;

  if (!ignore[0])
    aFile = dgOpen(name);
  buffer = xmalloc(strlen(name) * 2 + 2);
  sprintf(buffer, "%s-%s", name, name);
  if (!ignore[1])
    aaFile = dgOpen(buffer);

  if (!prefix)
    {
      prefix = xmalloc(2 * strlen(name) + 2);
      sprintf(prefix, "%s-%s", name, name);
    }

  buffer = xrealloc(buffer, strlen(prefix) + 10);
  strcpy(buffer, prefix);
  strcat(buffer, ".conc.run");
  if (!(outFile = fopen(buffer, "wt")))
    {
      perror(buffer);
      return EXIT_FAILURE;
    }
  now = time(NULL);
  fprintf(outFile, "concentration-same %s ran on %s at %s\n", PACKAGE_VERSION, name, ctime(&now));
  fprintf(outFile, "A0 = %g\n", A0);
  if (ignore[0])
    fputs("A ignored\n", outFile);
  if (ignore[1])
    fputs("AA ignored\n", outFile);
  if (finite(openEnthalpy))
    fprintf(outFile, "Enthalpy for unfolded strands: %g\n", openEnthalpy);
  if (finite(openEntropy))
    fprintf(outFile, "Entropy for unfolded strands: %g\n", openEntropy * 1000);
  if (power != 1.0)
    fprintf(outFile, "Exponent for unfolded strands: %g\n", power);
  fclose(outFile);
  buffer[strlen(buffer) - 4] = 0;
  if (!(outFile = fopen(buffer, "wt")))
    {
      perror(buffer);
      return EXIT_FAILURE;
    }
  free(buffer);

  if (zInfinity)
    {
      FILE* inf;
      
      buffer = xmalloc(strlen(name) * 2 + 6);
      sprintf(buffer, "%s.inf", name);
      if (!(inf = fopen(buffer, "rt")))
	{
	  perror(buffer);
	  return EXIT_FAILURE;
	}
      readOrDie(1, "inf", inf, "%lf", &ZaInf);
      fclose(inf);
      sprintf(buffer, "%s-%s.inf", name, name);
      if (!(inf = fopen(buffer, "rt")))
	{
	  perror(buffer);
	  return EXIT_FAILURE;
	}
      readOrDie(1, "inf", inf, "%lf", &ZaaInf);
      fclose(inf);
    }

  fputs("T\t[Af] (M)\t[A] (M)\t[AA] (M)\n", outFile);

  while (1)
    {
      Za = Zaa = 0;
      if ((!ignore[0] && fscanf(aFile, "%lg%*g%lg", &Ta, &Za) < 2) ||
	  (!ignore[1] && fscanf(aaFile, "%lg%*g%lg", &Taa, &Zaa) < 2))
	break;
 
      if (ignore[0])
	Ta = Taa;
      else if (ignore[1])
	Taa = Ta;

      /* skip to end(s) of line(s) */
      if (!ignore[0])
	for (c = 0; c != '\n'; readOrDie(1, "dG", aFile, "%c", &c));
      if (!ignore[1])
	for (c = 0; c != '\n'; readOrDie(1, "dG", aaFile, "%c", &c));
 
      printf("Calculating concentrations for %g\n", Ta);

      /* add 1 since hybrid-ss assumes at least one base pair */
      /* Za += 1; */
      /* Zau = exp(-openEnthalpy / R / (Ta + 273.15) + openEntropy / R) + 1; */
      if (finite(openEnthalpy) && finite(openEntropy))
	{
	  double Zs;
	  Zau = pow(1.0 + exp(-openEnthalpy / R / (Ta + 273.15) + openEntropy / R), power);
	  Zs = exp(power * (-openEnthalpy / R / (Ta + 273.15) + openEntropy / R));
	  Za *= Zs;
	  Zaa *= Zs * Zs;
	}
      else
	Zau = 1.0;
      Za += Zau;

      if (zInfinity)
	{
	  Za = (Za - ZaInf) / (ZaInf + 1.0);
	  Zaa = (Zaa - ZaaInf) / (ZaaInf + 1.0);
	}

      if (Ta != Taa)
	fprintf(stderr, "Warning: temperature mismatch: %g %g\n", Ta, Taa);
      
      lKa = log(Zaa) - 2.0 * log(Za);
      
      if (Zaa == 0)
	{
	  A = A0;
	  fprintf(outFile, "%g\t%g\t%g\t%g\n", Ta, A0 - A0 * Zau / Za, A0, 0.0);
	}
      else
	{
	  /* A = (-1 + sqrt(1 + 8 * Ka * A0)) / 4 / Ka; */
	  /* A = 2.0 * A0 / (1.0 + sqrt(1.0 + 8.0 * Ka * A0)); */
	  A = 2.0 * exp(lA0 - ln1pex(ln1pex(log(8.0) + lKa + lA0) / 2.0));
	  fprintf(outFile, "%g\t%g\t%g\t%g\n", Ta, A - A * Zau / Za, A, (A0 - A) / 2.0);
	}
    }

  if (!ignore[0])
    fclose(aFile);
  if (!ignore[1])
    fclose(aaFile);
  fclose(outFile);

  return EXIT_SUCCESS;
 }
Ejemplo n.º 8
0
bool HHVM_FUNCTION(is_finite, double val) { return finite(val);}
Ejemplo n.º 9
0
MINLINE bool is_finite_v4(const float v[4])
{
	return (finite(v[0]) && finite(v[1]) && finite(v[2]) && finite(v[3]));
}
Ejemplo n.º 10
0
/*--------------------------------------------------------------------------*/
int get_rect_arg(void* _pvCtx, char *fname, int pos, rhs_opts opts[], double ** rect)
{
    int m, n, first_opt = FirstOpt(_pvCtx), kopt, i;

    if (pos < first_opt)
    {
        int* piAddr = 0;
        int iType = 0;
        double* pdblData = NULL;
        getVarAddressFromPosition(_pvCtx, pos, &piAddr);
        getVarType(_pvCtx, piAddr, &iType);

        if (iType)
        {
            getMatrixOfDouble(_pvCtx, piAddr, &m, &n, &pdblData);
            if (m * n != 4)
            {
                Scierror(999, "%s: Wrong size for input argument #%d: %d expected\n", fname, pos, 4);
                return 0;
            }

            *rect = pdblData;

            for (i = 0; i < 4; i++)
            {
                if (finite((*rect)[i]) == 0)
                {
                    Scierror(999, "%s: Wrong values (Nan or Inf) for input argument: %d finite values expected\n", fname, 4);
                    return 0;
                }
            }
        }
        else
        {
            /** global value can be modified  **/
            double zeros[4] = { 0.0, 0.0, 0.0, 0.0 };
            setDefRect(zeros);
            *rect = getDefRect();
        }
    }
    else if ((kopt = FindOpt(_pvCtx, "rect", opts)) >= 0) /* named argument: rect=value */
    {
        double* pdblData = NULL;
        getMatrixOfDouble(_pvCtx, opts[kopt].piAddr, &m, &n, &pdblData);
        if (m * n != 4)
        {
            Scierror(999, "%s: Wrong size for input argument #%d: %d expected\n", fname, kopt, 4);
            return 0;
        }

        *rect = pdblData;

        for (i = 0; i < 4; i++)
        {
            if (finite((*rect)[i]) == 0)
            {
                Scierror(999, "%s: Wrong values (Nan or Inf) for input argument: %d finite values expected\n", fname, 4);
                return 0;
            }
        }
    }
    else
    {
        /** global value can be modified  **/
        double zeros[4] = { 0.0, 0.0, 0.0, 0.0 };
        setDefRect(zeros);
        *rect = getDefRect();
    }

    return 1;
}
Ejemplo n.º 11
0
/* Revamped version of LALDemod() (based on TestLALDemod() in CFS).
 * Compute JKS's Fa and Fb, which are ingredients for calculating the F-statistic.
 */
static int
LocalXLALComputeFaFb ( Fcomponents *FaFb,
                       const SFTVector *sfts,
                       const PulsarSpins fkdot,
                       const SSBtimes *tSSB,
                       const AMCoeffs *amcoe,
                       const ComputeFParams *params)       /* addition computational params */
{
  UINT4 alpha;                  /* loop index over SFTs */
  UINT4 spdnOrder;              /* maximal spindown-orders */
  UINT4 numSFTs;                /* number of SFTs (M in the Notes) */
  COMPLEX16 Fa, Fb;
  REAL8 Tsft;                   /* length of SFTs in seconds */
  INT4 freqIndex0;              /* index of first frequency-bin in SFTs */
  INT4 freqIndex1;              /* index of last frequency-bin in SFTs */

  REAL4 *a_al, *b_al;           /* pointer to alpha-arrays over a and b */
  REAL8 *DeltaT_al, *Tdot_al;   /* pointer to alpha-arrays of SSB-timings */
  SFTtype *SFT_al;              /* SFT alpha  */

  REAL8 norm = OOTWOPI;

  XLAL_CHECK ( params->Dterms == DTERMS, XLAL_EDOM );
#ifndef LAL_NDEBUG
  /* ----- check validity of input */
  if ( !FaFb ) {
    XLALPrintError ("\nOutput-pointer is NULL !\n\n");
    XLAL_ERROR ( XLAL_EINVAL);
  }

  if ( !sfts || !sfts->data ) {
    XLALPrintError ("\nInput SFTs are NULL!\n\n");
    XLAL_ERROR ( XLAL_EINVAL);
  }

  if ( !tSSB || !tSSB->DeltaT || !tSSB->Tdot || !amcoe || !amcoe->a || !amcoe->b || !params)
    {
      XLALPrintError ("\nIllegal NULL in input !\n\n");
      XLAL_ERROR ( XLAL_EINVAL);
    }

#endif

  /* ----- prepare convenience variables */
  numSFTs = sfts->length;
  Tsft = 1.0 / sfts->data[0].deltaF;
  {
    REAL8 dFreq = sfts->data[0].deltaF;
    freqIndex0 = lround ( sfts->data[0].f0 / dFreq ); /* lowest freqency-index */
    freqIndex1 = freqIndex0 + sfts->data[0].data->length;
  }

  static int firstcall = 1; /* for sin/cos lookup table initialization */
  if (firstcall)
    {
      /* init sin/cos lookup tables */
      local_sin_cos_2PI_LUT_init();

      /* make sure Dterms is what we expect */
      XLAL_CHECK (DTERMS == params->Dterms, XLAL_EINVAL, "LocalXLALComputeFaFb() has been compiled with fixed DTERMS (%d) != params->Dtems (%d)\n", DTERMS, params->Dterms );
      firstcall = 0;
    }

  /* find highest non-zero spindown-entry */
  for ( spdnOrder = PULSAR_MAX_SPINS - 1;  spdnOrder > 0 ; spdnOrder --  )
    if ( fkdot[spdnOrder] != 0.0 )
      break;

  Fa = 0.0f;
  Fb = 0.0f;

  a_al = amcoe->a->data;        /* point to beginning of alpha-arrays */
  b_al = amcoe->b->data;
  DeltaT_al = tSSB->DeltaT->data;
  Tdot_al = tSSB->Tdot->data;
  SFT_al = sfts->data;

  /* Loop over all SFTs  */
  for ( alpha = 0; alpha < numSFTs; alpha++ )
    {
      REAL4 a_alpha, b_alpha;

      INT4 kstar;               /* central frequency-bin k* = round(xhat_alpha) */
      INT4 k0, k1;

      COMPLEX8 *Xalpha = SFT_al->data->data; /* pointer to current SFT-data */
      REAL4 s_alpha, c_alpha;   /* sin(2pi kappa_alpha) and (cos(2pi kappa_alpha)-1) */
      REAL4 realQ, imagQ;       /* Re and Im of Q = e^{-i 2 pi lambda_alpha} */
      REAL4 realXP, imagXP;     /* re/im of sum_k X_ak * P_ak */
      REAL4 realQXP, imagQXP;   /* Re/Im of Q_alpha R_alpha */

      REAL8 lambda_alpha, kappa_star;

      /* ----- calculate lambda_alpha */
      {
        UINT4 s;                /* loop-index over spindown-order */
        REAL8 phi_alpha, Dphi_alpha, DT_al;
        REAL8 Tas;      /* temporary variable to calculate (DeltaT_alpha)^s */
        REAL8 TAS_invfact_s;

        /* init for s=0 */
        phi_alpha = 0.0;
        Dphi_alpha = 0.0;
        DT_al = (*DeltaT_al);
        Tas = 1.0;              /* DeltaT_alpha ^ 0 */
        TAS_invfact_s=1.0;    /* TAS / s! */

        for (s=0; s <= spdnOrder; s++) {
          REAL8 fsdot = fkdot[s];
          Dphi_alpha += fsdot * TAS_invfact_s;  /* here: DT^s/s! */
#ifdef EAH_CHECK_FINITE_DPHI
          if (!finite(Dphi_alpha)) {
            LogPrintf(LOG_CRITICAL, "non-finite Dphi_alpha:%e, alpha:%d, spind#:%d, fkdot:%e, Tas:%e, LAL_FACT_INV[s]:%e, LAL_FACT_INV[s+1]:%e, phi_alpha:%e. DT_al:%e\n",
                      Dphi_alpha, alpha, s, fkdot[s], Tas, LAL_FACT_INV[s], LAL_FACT_INV[s+1], phi_alpha, DT_al);
            XLAL_ERROR("LocalXLALComputeFaFb", XLAL_EDOM);
          }
#endif
          Tas *= DT_al;                         /* now: DT^(s+1) */
          TAS_invfact_s= Tas * LAL_FACT_INV[s+1];
          phi_alpha += fsdot * TAS_invfact_s;
        } /* for s <= spdnOrder */

        /* Step 3: apply global factors to complete Dphi_alpha */
        Dphi_alpha *= Tsft * (*Tdot_al);                /* guaranteed > 0 ! */
#ifndef EAH_NO_CHECK_FINITE_DPHI
        if (!finite(Dphi_alpha)) {
          LogPrintf(LOG_CRITICAL, "non-finite Dphi_alpha:%e, alpha:%d, Tsft:%e, Tkdot_al:%e Tas:%e, DT_al:%e\n",
                    Dphi_alpha, alpha, Tsft, (*Tdot_al), Tas, DT_al);
          XLAL_ERROR( XLAL_EDOM );
        }
#endif
        lambda_alpha = 0.5 * Dphi_alpha - phi_alpha;

        /* FIXME: that might be possible to do faster */
        kstar = (INT4) (Dphi_alpha);    /* k* = floor(Dphi_alpha*chi) for positive Dphi */
        kappa_star = Dphi_alpha - 1.0 * kstar;  /* remainder of Dphi_alpha: >= 0 ! */

        /* ----- check that required frequency-bins are found in the SFTs ----- */
        k0 = kstar - DTERMS + 1;
        /*
           original:
           k1 = k0 + 2 * DTERMS - 1;
           inserted k0:
           k1 = kstar - DTERMS + 1 + 2 * DTERMS - 1;
           shortened:
        */
        k1 = kstar + DTERMS;

        if ( (k0 < freqIndex0) || (k1 > freqIndex1) )
          {
            LogPrintf(LOG_CRITICAL,
                      "Required frequency-bins [%d, %d] not covered by SFT-interval [%d, %d]\n"
                      "\t\t[Parameters: alpha:%d, Dphi_alpha:%e, Tsft:%e, *Tdot_al:%e]\n",
                      k0, k1, freqIndex0, freqIndex1,
                      alpha, Dphi_alpha, Tsft, *Tdot_al);
            XLAL_ERROR(XLAL_EDOM);
          }

      } /* compute kappa_star, lambda_alpha */

      /* ---------- calculate the (truncated to DTERMS) sum over k ---------- */

      /* ---------- ATTENTION: this the "hot-loop", which will be
       * executed many millions of times, so anything in here
       * has a HUGE impact on the whole performance of the code.
       *
       * DON'T touch *anything* in here unless you really know
       * what you're doing !!
       *------------------------------------------------------------
       */

      {
        COMPLEX8 *Xalpha_l = Xalpha + k0 - freqIndex0;  /* first frequency-bin in sum */

        /* if no danger of denominator -> 0 */
#ifdef __GNUC__
        /* somehow the branch prediction of gcc-4.1.2 terribly failes
            with the current case distinction in the hot-loop,
            having a severe impact on runtime of the E@H Linux App.
            So let's allow to give gcc a hint which path has a higher probablility */
        if (__builtin_expect((kappa_star > LD_SMALL4) && (kappa_star < 1.0 - LD_SMALL4), (0==0)))
#else
        if ((kappa_star > LD_SMALL4) && (kappa_star < 1.0 - LD_SMALL4))
#endif
          {
          /* WARNING: all current optimized loops rely on current implementation of COMPLEX8 and DTERMS == 8 */

#include OPT_DEMOD_SOURCE

          } /* if |remainder| > LD_SMALL4 */
        else
          { /* otherwise: lim_{rem->0}P_alpha,k  = 2pi delta_{k,kstar} */
            UINT4 ind0;

            /* realQ/imagQ are calculated in the hotloop in the other case; in this case we have to do it too */
            SINCOS_TRIM_X (lambda_alpha,lambda_alpha);
            SINCOS_2PI_TRIMMED( &imagQ, &realQ, lambda_alpha );

            if ( kappa_star <= LD_SMALL4 ) {
              ind0 = DTERMS - 1;
            } else {
              ind0 = DTERMS;
            }

            realXP = TWOPI_FLOAT * crealf(Xalpha_l[ind0]);
            imagXP = TWOPI_FLOAT * cimagf(Xalpha_l[ind0]);

          } /* if |remainder| <= LD_SMALL4 */
      }

      /* real- and imaginary part of e^{-i 2 pi lambda_alpha } */

      realQXP = realQ * realXP - imagQ * imagXP;
      imagQXP = realQ * imagXP + imagQ * realXP;


      /* we're done: ==> combine these into Fa and Fb */

      a_alpha = (*a_al);
      b_alpha = (*b_al);

      Fa += crect( a_alpha * realQXP, a_alpha * imagQXP );

      Fb += crect( b_alpha * realQXP, b_alpha * imagQXP );

      /* advance pointers over alpha */
      a_al ++;
      b_al ++;
      DeltaT_al ++;
      Tdot_al ++;
      SFT_al ++;

    } /* for alpha < numSFTs */

  /* return result */
  FaFb->Fa = norm * Fa;
  FaFb->Fb = norm * Fb;

  return XLAL_SUCCESS;

} // LocalXLALComputeFaFb()
Ejemplo n.º 12
0
double
erfc(double x)
{
	double R, S, P, Q, s, ax, y, z, r;
	if (!finite(x)) {
		if (isnan(x))		/* erfc(NaN) = NaN */
			return(x);
		else if (x > 0)		/* erfc(+-inf)=0,2 */
			return 0.0;
		else
			return 2.0;
	}
	if ((ax = x) < 0)
		ax = -ax;
	if (ax < .84375) {			/* |x|<0.84375 */
	    if (ax < 1.38777878078144568e-17)  	/* |x|<2**-56 */
		return one-x;
	    y = x*x;
	    r = y*(p1+y*(p2+y*(p3+y*(p4+y*(p5+
			y*(p6+y*(p7+y*(p8+y*(p9+y*p10)))))))));
	    if (ax < .0625) {  	/* |x|<2**-4 */
		return (one-(x+x*(p0+r)));
	    } else {
		r = x*(p0+r);
		r += (x-half);
	        return (half - r);
	    }
	}
	if (ax < 1.25) {		/* 0.84375 <= |x| < 1.25 */
	    s = ax-one;
	    P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6)))));
	    Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6)))));
	    if (x>=0) {
	        z  = one-c; return z - P/Q;
	    } else {
		z = c+P/Q; return one+z;
	    }
	}
	if (ax >= 28)	/* Out of range */
 		if (x>0)
			return (tiny*tiny);
		else
			return (two-tiny);
	z = ax;
	TRUNC(z);
	y = z - ax; y *= (ax+z);
	z *= -z;			/* Here z + y = -x^2 */
		s = one/(-z-y);		/* 1/(x*x) */
	if (ax >= 4) {			/* 6 <= ax */
		R = s*(rd1+s*(rd2+s*(rd3+s*(rd4+s*(rd5+
			s*(rd6+s*(rd7+s*(rd8+s*(rd9+s*(rd10
			+s*(rd11+s*(rd12+s*rd13))))))))))));
		y += rd0;
	} else if (ax >= 2) {
		R = rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(rb5+
			s*(rb6+s*(rb7+s*(rb8+s*(rb9+s*rb10)))))))));
		S = one+s*(sb1+s*(sb2+s*sb3));
		y += R/S;
		R = -.5*s;
	} else {
		R = rc0+s*(rc1+s*(rc2+s*(rc3+s*(rc4+s*(rc5+
			s*(rc6+s*(rc7+s*(rc8+s*(rc9+s*rc10)))))))));
		S = one+s*(sc1+s*(sc2+s*sc3));
		y += R/S;
		R = -.5*s;
	}
	/* return exp(-x^2 - lsqrtPI_hi + R + y)/x;	*/
	s = ((R + y) - lsqrtPI_hi) + z;
	y = (((z-s) - lsqrtPI_hi) + R) + y;
	r = __exp__D(s, y)/x;
	if (x>0)
		return r;
	else
		return two-r;
}
Ejemplo n.º 13
0
double svm_kernel_fisher(bow_wv *wv1, bow_wv *wv2) {
  bow_cdoc  *cd;
  int        max_entries;   /* max number of elements that can be in both */
  int        nclasses;
  int        nwords;
  NPair     *Nvector;
  double     rval;
  double     tmp;
  bow_we    *v1, *v2;

  double t2, pci;
  int i, j, k;

  nwords = total_num_words_occurences;
  nclasses = bow_barrel_num_classes(rainbow_nb_barrel);
  max_entries = MIN(wv1->num_entries, wv2->num_entries);

  Nvector = (NPair *) alloca(max_entries*sizeof(NPair));

  v1 = wv1->entry;
  v2 = wv2->entry;

  /* compute the N(wi,X1)*N(wi,X2) vector */
  for (i=j=k=0; (i<max_entries) && (j<max_entries); ) {
    if(v1[i].wi > v2[j].wi) {
      j++;
    }
    else if (v1[i].wi < v2[j].wi) {
      i++;
    }
    else {
      Nvector[k].index = v1[i].wi;
      Nvector[k].N = (v1[i].count)*(v2[j].count);
      k++;
      i++;
      j++;
    }
  }

  max_entries = k;
  rval = 0.0;

  /* now we have all of the P(X*|C*) terms - in ascending order with
   * regards to class index */
  for (i=0; i<nclasses; i++) {
    for (j=0, tmp=0; j<max_entries; j++) {
      t2 = bow_naivebayes_pr_wi_ci(rainbow_nb_barrel, Nvector[j].index, i, -1, 0, 0, NULL, NULL);
      t2 = t2*t2;
      tmp += Nvector[j].N / (dIij[i*nclasses + Nvector[j].index] * t2);
      assert(finite(tmp));
    }

    /* compute P(x[12]|ci)/P(x[12]) */
    {
      double p_w;
      bow_we *v;
      bow_wv *w;
      int k,h,n;
      
      t2 = fisher_norm0;

      for (w=wv1, n=0; n<2; n++, w=wv2) {
	v = w->entry;
	for (h=0; h<w->num_entries; h++) {
	  double sum, t;
	  bow_dv *dv = bow_wi2dvf_dv(rainbow_nb_barrel->wi2dvf, v[h].wi);
	  assert(dv);
	  /* sum up the number of words that appeared in all of the classes */
	  for (k=0, sum=0.0; k<dv->length; k++) {
	    sum += dv->entry[k].weight;
	  }

	  p_w = log(sum/nwords)*v[h].weight;
	  t = (double) bow_naivebayes_pr_wi_ci (rainbow_nb_barrel, v[h].wi, i, -1,
						       0.0, 0.0, NULL, NULL);
	  t = log(t) * v[h].weight;
	  t2 += t - p_w;
	  assert(finite(t2));
	  //printf("P(w%d|c%d)^%f, p_w^%f\n", v[h].wi, k, t, p_w);
	}
      }
    }

    cd = GET_CDOC_ARRAY_EL(rainbow_nb_barrel,i);
    pci = cd->prior;
    rval += exp(t2 + log(dIi[i] + (tmp*pci*pci)));
    assert(finite(rval));
  }

  //rval = exp(rval);

  printf("kernel=%f\n",rval);
  return rval;
}
Ejemplo n.º 14
0
void svm_setup_fisher(bow_barrel *old_barrel, bow_wv **docs, int nclasses, int ndocs) {
  double *PXk, PX;
  int     i,j,k;

  rainbow_method *tmp = old_barrel->method;

  old_barrel->method = &bow_method_naivebayes;
  rainbow_nb_barrel = bow_barrel_new_vpc_merge_then_weight (old_barrel);
  old_barrel->method = tmp;

    /* set some global variables that naivebayes.c uses */
  naivebayes_score_returns_doc_pr = 1;
  naivebayes_score_unsorted = 1;

  fprintf(stderr, "Finding maximum kernel value for normalizing\n");

  i = bow_num_words()*nclasses;
  dIi = (double *) malloc(sizeof(double)*nclasses);
  PXk = (double *) malloc(sizeof(double)*nclasses);
  dIij = (double *) malloc(sizeof(double)*i);

  for (j=0; j<i; j++) {
    dIij[j] = 0.0;
  }

  for (j=0; j<nclasses; j++) {
    dIi[j] = 0.0;
  }

  for (i=0; i<ndocs; i++) {
    double max_lpr;
    bow_score *scores = malloc(sizeof(bow_score)*nclasses);

    /* compute the P(X|class) * P(class) terms (since they're used so often) */
    PX = 0.0;
    /* NOTE: with the ...returns_doc_pr variable set, the scores are not probabilities,
     * but instead log probabilities */
    bow_naivebayes_score(rainbow_nb_barrel, docs[i], scores, nclasses, -1);

    max_lpr = scores[0].weight;
    for (k=1; k<nclasses; k++) {
      if (scores[k].weight > max_lpr) 
	max_lpr = scores[k].weight;
    }

    for (k=0; k<nclasses; k++) {
      bow_cdoc *cd = GET_CDOC_ARRAY_EL(rainbow_nb_barrel,k);
      /* the max lpr over everything is the same as multiplying both the
       * denominator & the numerator by some large constant */
      PXk[k] = cd->prior * exp(scores[k].weight - max_lpr);
      /* hacky-hacky-hacky-smoothing */
#define THRESH 1e-1
      if (PXk[k] < THRESH) {
	PXk[k] = THRESH;
	printf("underflow on P(X%d|C%d) - setting to small val\n",i,k);
	fflush(stdout);
      }
      PX += PXk[k];
      assert(finite(PXk[k]) && PXk[k] != 0.0);
    }
    free(scores);


    /* compute term for Iij - d/d-theta_ij * log(P(X|theta)) */
    for (j=0; j<docs[i]->num_entries; j++) {
      for (k=0; k<nclasses; k++) {
	double tmp;

	tmp = bow_naivebayes_pr_wi_ci (rainbow_nb_barrel, docs[i]->entry[j].wi,
				       k, -1, 0.0, 0.0, NULL, NULL);

	dIij[k*nclasses + docs[i]->entry[j].wi] += 
	  ((((docs[i]->entry[j].count * PXk[k]) /tmp) /PX) * 
	   (((docs[i]->entry[j].count * PXk[k]) /tmp) /PX));
      }
    }

    /* compute term for Ii - d/d-theta_i * log(P(X|theta)) */
    for (k=0; k<nclasses; k++) {
      /* M is in both of these terms, so we don't need to worry about it... */
      dIi[k] += (PXk[k]/ PX)*(PXk[k]/ PX);
      assert(finite(dIi[k]));
    }

    if (!(i % 100)) {
      fprintf(stderr, "\r%f%%", (float) ((double)i)/((double)ndocs)*100.0);
    }
  }
  free(PXk);

    /* now invert the values class values */
  for (i=0; i<nclasses; i++) {
    dIi[i] = 1/dIi[i];
  }

  fprintf(stderr,"%f%%\n",(float)100.0);

    /* set "fisher normalizer" */
  {
    double max = -1;     
    int from=0;
    fisher_norm0 = 0;  /* keep in mind, this is log(scalar) */
    for (i=0; i<ndocs; i++) {
      double tmp = svm_kernel_fisher(docs[i],docs[i]);
      if (max < tmp) {
	max = tmp;
	from = i;
      }
    }
    fisher_norm0 = log(1/max);
  }
}
Ejemplo n.º 15
0
// feed adaptation data from an alignment into the adaptation process
// note: it is possible to accumulate statistics at the Gaussian component or at the transform level
// - Gaussian component level: O(n^2) per Gaussian component
// - Transform level: O(n^3) per transform + O(n) per Gaussian component
void FMLLREstimator::feedAdaptationData(MatrixBase<float> &mFeatures, Alignment *alignment, double *dLikelihood) {

	// sanity check
	assert((unsigned int)mFeatures.getRows() == alignment->getFrames());

	m_fOccupancyTotal += mFeatures.getRows();

	*dLikelihood = 0.0;
	for(unsigned int t=0 ; t<mFeatures.getRows() ; ++t) {
		
		VectorStatic<float> vFeatureVector = mFeatures.getRow(t);
		
		// extended observation vector
		Vector<double> vObsEx(vFeatureVector);
		vObsEx.appendFront(1.0);	
		
		// for each HMM-state the observation is assigned to
		FrameAlignment *frameAlignment = alignment->getFrameAlignment(t);
		for(FrameAlignment::iterator it = frameAlignment->begin() ; it != frameAlignment->end() ; ++it) {
			HMMStateDecoding *hmmStateDecoding = m_hmmManager->getHMMStateDecoding((*it)->iHMMState);
			// compute the contribution of each Gaussian 
			// (case 1) all the frame-level adaptation data goes to the best scoring Gaussian component (faster)
			if (m_bBestComponentOnly) {
				float fLikelihood = -FLT_MAX;
				GaussianDecoding *gaussian = hmmStateDecoding->getBestScoringGaussian(vFeatureVector.getData(),&fLikelihood);
				*dLikelihood += std::max<float>(fLikelihood,LOG_LIKELIHOOD_FLOOR);
					
				Vector<float> vCovariance(VectorStatic<float>(gaussian->fCovariance,m_iDim));		
			#ifdef OPTIMIZED_COMPUTATION
				vCovariance.mul(2.0);
				vCovariance.invertElements();
			#endif

				// accumulate data for each G(i)
				m_matrixAux->zero();
				m_matrixAux->addVecMul(1.0,vObsEx,vObsEx);
				for(int i=0 ; i < m_iDim; ++i) {
					double dCovInv = 1.0/vCovariance(i);
					m_matrixG[i]->add(dCovInv*1.0,*m_matrixAux);
				}
				
				// accumulate data for each k(i)
				for(int i=0 ; i < m_iDim ; ++i) {	
					double dConstant = (gaussian->fMean[i]/vCovariance(i))*1.0;
					m_matrixK->getRow(i).add(dConstant,vObsEx);
				}	
			}
			// (case 2) adaptation data is shared across all components (slightly more accurate)
			else {			
				double *dProbGaussian = new double[hmmStateDecoding->getGaussianComponents()];
				double dProbTotal = 0.0;
				for(int g=0 ; g < hmmStateDecoding->getGaussianComponents() ; ++g) {	
					dProbGaussian[g] = exp(hmmStateDecoding->computeGaussianProbability(g,vFeatureVector.getData()));
					dProbTotal += dProbGaussian[g];
					assert((finite(dProbGaussian[g])) && (finite(dProbTotal)));	
				}
				*dLikelihood += max(log(dProbTotal),LOG_LIKELIHOOD_FLOOR);
				for(unsigned int iGaussian = 0 ; iGaussian < hmmStateDecoding->getMixtureSize() ; ++iGaussian) {
				
					GaussianDecoding *gaussian = hmmStateDecoding->getGaussian(iGaussian);	
					double dGaussianOccupation = dProbGaussian[iGaussian]/dProbTotal;
					
					Vector<float> vCovariance(VectorStatic<float>(gaussian->fCovariance,m_iDim));		
				#ifdef OPTIMIZED_COMPUTATION
					vCovariance.mul(2.0);
					vCovariance.invertElements();
				#endif
	
					// accumulate data for each G(i)
					m_matrixAux->zero();
					m_matrixAux->addVecMul(1.0,vObsEx,vObsEx);
					for(int i=0 ; i < m_iDim; ++i) {
						double dCovInv = 1.0/vCovariance(i);
						m_matrixG[i]->add(dCovInv*dGaussianOccupation,*m_matrixAux);
					}
					
					// accumulate data for each k(i)
					for(int i=0 ; i < m_iDim ; ++i) {	
						double dConstant = (gaussian->fMean[i]/vCovariance(i))*dGaussianOccupation;
						m_matrixK->getRow(i).add(dConstant,vObsEx);
					}
				}
				delete [] dProbGaussian;
			}
		}
	}
}
Ejemplo n.º 16
0
Archivo: lex.c Proyecto: dkastner/sc
int
yylex()
{
    char *p = line + linelim;
    int ret;
    static int isfunc = 0;
    static bool isgoto = 0;
    static bool colstate = 0;
    static int dateflag;
    static char *tokenst = NULL;
    static int tokenl;

    while (isspace(*p)) p++;
    if (*p == '\0') {
	isfunc = isgoto = 0;
	ret = -1;
    } else if (isalpha(*p) || (*p == '_')) {
	register char *la;	/* lookahead pointer */
	register struct key *tblp;

	if (!tokenst) {
	    tokenst = p;
	    tokenl = 0;
	}
	/*
	 *  This picks up either 1 or 2 alpha characters (a column) or
	 *  tokens made up of alphanumeric chars and '_' (a function or
	 *  token or command or a range name)
	 */
	while (isalpha(*p) && isascii(*p)) {
	    p++;
	    tokenl++;
	}
	la = p;
	while (isdigit(*la) || (*la == '$'))
	    la++;
	/*
	 * A COL is 1 or 2 char alpha with nothing but digits following
	 * (no alpha or '_')
	 */
	if (!isdigit(*tokenst) && tokenl && tokenl <= 2 && (colstate ||
		(isdigit(*(la-1)) && !(isalpha(*la) || (*la == '_'))))) {
	    ret = COL;
	    yylval.ival = atocol(tokenst, tokenl);
	} else {
	    while (isalpha(*p) || (*p == '_') || isdigit(*p)) {
		p++;
		tokenl++;
	    }
	    ret = WORD;
	    if (!linelim || isfunc) {
		if (isfunc) isfunc--;
		for (tblp = linelim ? experres : statres; tblp->key; tblp++)
		    if (((tblp->key[0]^tokenst[0])&0137)==0
			    && tblp->key[tokenl]==0) {
			int i = 1;
			while (i<tokenl && ((tokenst[i]^tblp->key[i])&0137)==0)
			    i++;
			if (i >= tokenl) {
			    ret = tblp->val;
			    colstate = (ret <= S_FORMAT);
			    if (isgoto) {
				isfunc = isgoto = 0;
				if (ret != K_ERROR && ret != K_INVALID)
				    ret = WORD;
			    }
			    break;
			}
		    }
	    }
	    if (ret == WORD) {
		struct range *r;
		char *path;
		if (!find_range(tokenst, tokenl,
			(struct ent *)0, (struct ent *)0, &r)) {
		    yylval.rval.left = r->r_left;
		    yylval.rval.right = r->r_right;
		    if (r->r_is_range)
		        ret = RANGE;
		    else
			ret = VAR;
		} else if ((path = scxmalloc((unsigned)PATHLEN)) &&
			plugin_exists(tokenst, tokenl, path)) {
		    strcat(path, p);
		    yylval.sval = path;
		    ret = PLUGIN;
		} else {
		    scxfree(path);
		    linelim = p-line;
		    yyerror("Unintelligible word");
		}
	    }
	}
    } else if ((*p == '.') || isdigit(*p)) {
#ifdef SIGVOID
	void (*sig_save)();
#else
	int (*sig_save)();
#endif
	double v = 0.0;
	int temp;
	char *nstart = p;

	sig_save = signal(SIGFPE, fpe_trap);
	if (setjmp(fpe_buf)) {
	    (void) signal(SIGFPE, sig_save);
	    yylval.fval = v;
	    error("Floating point exception\n");
	    isfunc = isgoto = 0;
	    tokenst = NULL;
	    return FNUMBER;
	}

	if (*p=='.' && dateflag) {  /* .'s in dates are returned as tokens. */
	    ret = *p++;
	    dateflag--;
	} else {
	    if (*p != '.') {
		tokenst = p;
		tokenl = 0;
		do {
		    v = v*10.0 + (double) ((unsigned) *p - '0');
		    tokenl++;
		} while (isdigit(*++p));
		if (dateflag) {
		    ret = NUMBER;
		    yylval.ival = (int)v;
		/*
		 *  If a string of digits is followed by two .'s separated by
		 *  one or two digits, assume this is a date and return the
		 *  .'s as tokens instead of interpreting them as decimal
		 *  points.  dateflag counts the .'s as they're returned.
		 */
		} else if (*p=='.' && isdigit(*(p+1)) && (*(p+2)=='.' ||
			(isdigit(*(p+2)) && *(p+3)=='.'))) {
		    ret = NUMBER;
		    yylval.ival = (int)v;
		    dateflag = 2;
		} else if (*p == 'e' || *p == 'E') {
		    while (isdigit(*++p)) /* */;
		    if (isalpha(*p) || *p == '_') {
			linelim = p - line;
			return (yylex());
		    } else
			ret = FNUMBER;
		} else if (isalpha(*p) || *p == '_') {
		    linelim = p - line;
		    return (yylex());
		}
	    }
	    if ((!dateflag && *p=='.') || ret == FNUMBER) {
		ret = FNUMBER;
		yylval.fval = strtod(nstart, &p);
		if (!finite(yylval.fval))
		    ret = K_ERR;
		else
		    decimal = TRUE;
	    } else {
		/* A NUMBER must hold at least MAXROW and MAXCOL */
		/* This is consistent with a short row and col in struct ent */
		if (v > (double)32767 || v < (double)-32768) {
		    ret = FNUMBER;
		    yylval.fval = v;
		} else {
		    temp = (int)v;
		    if((double)temp != v) {
			ret = FNUMBER;
			yylval.fval = v;
		    } else {
			ret = NUMBER;
			yylval.ival = temp;
		    }
		}
	    }
	}
	(void) signal(SIGFPE, sig_save);
    } else if (*p=='"') {
	char *ptr;
        ptr = p+1;	/* "string" or "string\"quoted\"" */
        while (*ptr && ((*ptr != '"') || (*(ptr-1) == '\\')))
	    ptr++;
        ptr = scxmalloc((unsigned)(ptr-p));
	yylval.sval = ptr;
	p++;
	while (*p && ((*p != '"') ||
		(*(p-1) == '\\' && *(p+1) != '\0' && *(p+1) != '\n')))
	    *ptr++ = *p++;
	*ptr = '\0';
	if (*p)
	    p++;
	ret = STRING;
    } else if (*p=='[') {
	while (*p && *p!=']')
	    p++;
	if (*p)
	    p++;
	linelim = p-line;
	tokenst = NULL;
	return yylex();
    } else ret = *p++;
    linelim = p-line;
    if (!isfunc) isfunc = ((ret == '@') + (ret == S_GOTO) - (ret == S_SET));
    if (ret == S_GOTO) isgoto = TRUE;
    tokenst = NULL;
    return ret;
}
Ejemplo n.º 17
0
/**
 * Validate the mesh, \a do_fixes requires \a mesh to be non-null.
 *
 * \return false if no changes needed to be made.
 */
bool BKE_mesh_validate_arrays(Mesh *mesh,
                              MVert *mverts, unsigned int totvert,
                              MEdge *medges, unsigned int totedge,
                              MFace *mfaces, unsigned int totface,
                              MLoop *mloops, unsigned int totloop,
                              MPoly *mpolys, unsigned int totpoly,
                              MDeformVert *dverts, /* assume totvert length */
                              const bool do_verbose, const bool do_fixes,
                              bool *r_change)
{
#   define REMOVE_EDGE_TAG(_me) { _me->v2 = _me->v1; do_edge_free = true; } (void)0
#   define IS_REMOVED_EDGE(_me) (_me->v2 == _me->v1)

#   define REMOVE_LOOP_TAG(_ml) { _ml->e = INVALID_LOOP_EDGE_MARKER; do_polyloop_free = true; } (void)0
#   define REMOVE_POLY_TAG(_mp) { _mp->totloop *= -1; do_polyloop_free = true; } (void)0

	MVert *mv = mverts;
	MEdge *me;
	MLoop *ml;
	MPoly *mp;
	unsigned int i, j;
	int *v;

	bool is_valid = true;

	bool do_edge_free = false;
	bool do_face_free = false;
	bool do_polyloop_free = false; /* This regroups loops and polys! */

	bool verts_fixed = false;
	bool vert_weights_fixed = false;
	bool msel_fixed = false;

	bool do_edge_recalc = false;

	EdgeHash *edge_hash = BLI_edgehash_new_ex(__func__, totedge);

	BLI_assert(!(do_fixes && mesh == NULL));

	PRINT_MSG("%s: verts(%u), edges(%u), loops(%u), polygons(%u)\n",
	          __func__, totvert, totedge, totloop, totpoly);

	if (totedge == 0 && totpoly != 0) {
		PRINT_ERR("\tLogical error, %u polygons and 0 edges\n", totpoly);
		do_edge_recalc = do_fixes;
	}

	for (i = 1; i < totvert; i++, mv++) {
		int fix_normal = TRUE;

		for (j = 0; j < 3; j++) {
			if (!finite(mv->co[j])) {
				PRINT_ERR("\tVertex %u: has invalid coordinate\n", i);

				if (do_fixes) {
					zero_v3(mv->co);

					verts_fixed = TRUE;
				}
			}

			if (mv->no[j] != 0)
				fix_normal = FALSE;
		}

		if (fix_normal) {
			PRINT_ERR("\tVertex %u: has zero normal, assuming Z-up normal\n", i);
			if (do_fixes) {
				mv->no[2] = SHRT_MAX;
				verts_fixed = TRUE;
			}
		}
	}

	for (i = 0, me = medges; i < totedge; i++, me++) {
		int remove = FALSE;
		if (me->v1 == me->v2) {
			PRINT_ERR("\tEdge %u: has matching verts, both %u\n", i, me->v1);
			remove = do_fixes;
		}
		if (me->v1 >= totvert) {
			PRINT_ERR("\tEdge %u: v1 index out of range, %u\n", i, me->v1);
			remove = do_fixes;
		}
		if (me->v2 >= totvert) {
			PRINT_ERR("\tEdge %u: v2 index out of range, %u\n", i, me->v2);
			remove = do_fixes;
		}

		if (BLI_edgehash_haskey(edge_hash, me->v1, me->v2)) {
			PRINT_ERR("\tEdge %u: is a duplicate of %d\n", i,
			          GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, me->v1, me->v2)));
			remove = do_fixes;
		}

		if (remove == FALSE) {
			BLI_edgehash_insert(edge_hash, me->v1, me->v2, SET_INT_IN_POINTER(i));
		}
		else {
			REMOVE_EDGE_TAG(me);
		}
	}

	if (mfaces && !mpolys) {
#		define REMOVE_FACE_TAG(_mf) { _mf->v3 = 0; do_face_free = TRUE; } (void)0
#		define CHECK_FACE_VERT_INDEX(a, b) \
					if (mf->a == mf->b) { \
						PRINT_ERR("    face %u: verts invalid, " STRINGIFY(a) "/" STRINGIFY(b) " both %u\n", i, mf->a); \
						remove = do_fixes; \
					} (void)0
#		define CHECK_FACE_EDGE(a, b) \
					if (!BLI_edgehash_haskey(edge_hash, mf->a, mf->b)) { \
						PRINT_ERR("    face %u: edge " STRINGIFY(a) "/" STRINGIFY(b) \
						          " (%u,%u) is missing edge data\n", i, mf->a, mf->b); \
						do_edge_recalc = TRUE; \
					} (void)0

		MFace *mf;
		MFace *mf_prev;

		SortFace *sort_faces = MEM_callocN(sizeof(SortFace) * totface, "search faces");
		SortFace *sf;
		SortFace *sf_prev;
		unsigned int totsortface = 0;

		PRINT_ERR("No Polys, only tesselated Faces\n");

		for (i = 0, mf = mfaces, sf = sort_faces; i < totface; i++, mf++) {
			int remove = FALSE;
			int fidx;
			unsigned int fv[4];

			fidx = mf->v4 ? 3 : 2;
			do {
				fv[fidx] = *(&(mf->v1) + fidx);
				if (fv[fidx] >= totvert) {
					PRINT_ERR("\tFace %u: 'v%d' index out of range, %u\n", i, fidx + 1, fv[fidx]);
					remove = do_fixes;
				}
			} while (fidx--);

			if (remove == FALSE) {
				if (mf->v4) {
					CHECK_FACE_VERT_INDEX(v1, v2);
					CHECK_FACE_VERT_INDEX(v1, v3);
					CHECK_FACE_VERT_INDEX(v1, v4);

					CHECK_FACE_VERT_INDEX(v2, v3);
					CHECK_FACE_VERT_INDEX(v2, v4);

					CHECK_FACE_VERT_INDEX(v3, v4);
				}
				else {
					CHECK_FACE_VERT_INDEX(v1, v2);
					CHECK_FACE_VERT_INDEX(v1, v3);

					CHECK_FACE_VERT_INDEX(v2, v3);
				}

				if (remove == FALSE) {
					if (totedge) {
						if (mf->v4) {
							CHECK_FACE_EDGE(v1, v2);
							CHECK_FACE_EDGE(v2, v3);
							CHECK_FACE_EDGE(v3, v4);
							CHECK_FACE_EDGE(v4, v1);
						}
						else {
							CHECK_FACE_EDGE(v1, v2);
							CHECK_FACE_EDGE(v2, v3);
							CHECK_FACE_EDGE(v3, v1);
						}
					}

					sf->index = i;

					if (mf->v4) {
						edge_store_from_mface_quad(sf->es, mf);

						qsort(sf->es, 4, sizeof(int64_t), int64_cmp);
					}
					else {
						edge_store_from_mface_tri(sf->es, mf);
						qsort(sf->es, 3, sizeof(int64_t), int64_cmp);
					}

					totsortface++;
					sf++;
				}
			}

			if (remove) {
				REMOVE_FACE_TAG(mf);
			}
		}

		qsort(sort_faces, totsortface, sizeof(SortFace), search_face_cmp);

		sf = sort_faces;
		sf_prev = sf;
		sf++;

		for (i = 1; i < totsortface; i++, sf++) {
			int remove = FALSE;

			/* on a valid mesh, code below will never run */
			if (memcmp(sf->es, sf_prev->es, sizeof(sf_prev->es)) == 0) {
				mf = mfaces + sf->index;

				if (do_verbose) {
					mf_prev = mfaces + sf_prev->index;

					if (mf->v4) {
						PRINT_ERR("\tFace %u & %u: are duplicates (%u,%u,%u,%u) (%u,%u,%u,%u)\n",
						          sf->index, sf_prev->index, mf->v1, mf->v2, mf->v3, mf->v4,
						          mf_prev->v1, mf_prev->v2, mf_prev->v3, mf_prev->v4);
					}
					else {
						PRINT_ERR("\tFace %u & %u: are duplicates (%u,%u,%u) (%u,%u,%u)\n",
						          sf->index, sf_prev->index, mf->v1, mf->v2, mf->v3,
						          mf_prev->v1, mf_prev->v2, mf_prev->v3);
					}
				}

				remove = do_fixes;
			}
			else {
				sf_prev = sf;
			}

			if (remove) {
				REMOVE_FACE_TAG(mf);
			}
		}

		MEM_freeN(sort_faces);

#		undef REMOVE_FACE_TAG
#		undef CHECK_FACE_VERT_INDEX
#		undef CHECK_FACE_EDGE
	}

	/* Checking loops and polys is a bit tricky, as they are quite intricated...
	 *
	 * Polys must have:
	 * - a valid loopstart value.
	 * - a valid totloop value (>= 3 and loopstart+totloop < me.totloop).
	 *
	 * Loops must have:
	 * - a valid v value.
	 * - a valid e value (corresponding to the edge it defines with the next loop in poly).
	 *
	 * Also, loops not used by polys can be discarded.
	 * And "intersecting" loops (i.e. loops used by more than one poly) are invalid,
	 * so be sure to leave at most one poly per loop!
	 */
	{
		SortPoly *sort_polys = MEM_callocN(sizeof(SortPoly) * totpoly, "mesh validate's sort_polys");
		SortPoly *prev_sp, *sp = sort_polys;
		int prev_end;
		for (i = 0, mp = mpolys; i < totpoly; i++, mp++, sp++) {
			sp->index = i;

			if (mp->loopstart < 0 || mp->totloop < 3) {
				/* Invalid loop data. */
				PRINT_ERR("\tPoly %u is invalid (loopstart: %u, totloop: %u)\n",
				          sp->index, mp->loopstart, mp->totloop);
				sp->invalid = TRUE;
			}
			else if (mp->loopstart + mp->totloop > totloop) {
				/* Invalid loop data. */
				PRINT_ERR("\tPoly %u uses loops out of range (loopstart: %u, loopend: %u, max nbr of loops: %u)\n",
				          sp->index, mp->loopstart, mp->loopstart + mp->totloop - 1, totloop - 1);
				sp->invalid = TRUE;
			}
			else {
				/* Poly itself is valid, for now. */
				int v1, v2; /* v1 is prev loop vert idx, v2 is current loop one. */
				sp->invalid = FALSE;
				sp->verts = v = MEM_mallocN(sizeof(int) * mp->totloop, "Vert idx of SortPoly");
				sp->numverts = mp->totloop;
				sp->loopstart = mp->loopstart;

				/* Test all poly's loops' vert idx. */
				for (j = 0, ml = &mloops[sp->loopstart]; j < mp->totloop; j++, ml++, v++) {
					if (ml->v >= totvert) {
						/* Invalid vert idx. */
						PRINT_ERR("\tLoop %u has invalid vert reference (%u)\n", sp->loopstart + j, ml->v);
						sp->invalid = TRUE;
					}

					mverts[ml->v].flag |= ME_VERT_TMP_TAG;
					*v = ml->v;
				}

				/* is the same vertex used more than once */
				if (!sp->invalid) {
					v = sp->verts;
					for (j = 0; j < mp->totloop; j++, v++) {
						if ((mverts[*v].flag & ME_VERT_TMP_TAG) == 0) {
							PRINT_ERR("\tPoly %u has duplicate vert reference at corner (%u)\n", i, j);
							sp->invalid = TRUE;
						}
						mverts[*v].flag &= ~ME_VERT_TMP_TAG;
					}
				}

				if (sp->invalid)
					continue;

				/* Test all poly's loops. */
				for (j = 0, ml = &mloops[sp->loopstart]; j < mp->totloop; j++, ml++) {
					v1 = ml->v;
					v2 = mloops[sp->loopstart + (j + 1) % mp->totloop].v;
					if (!BLI_edgehash_haskey(edge_hash, v1, v2)) {
						/* Edge not existing. */
						PRINT_ERR("\tPoly %u needs missing edge (%u, %u)\n", sp->index, v1, v2);
						if (do_fixes)
							do_edge_recalc = TRUE;
						else
							sp->invalid = TRUE;
					}
					else if (ml->e >= totedge) {
						/* Invalid edge idx.
						 * We already know from previous text that a valid edge exists, use it (if allowed)! */
						if (do_fixes) {
							int prev_e = ml->e;
							ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, v1, v2));
							PRINT_ERR("\tLoop %u has invalid edge reference (%u), fixed using edge %u\n",
							          sp->loopstart + j, prev_e, ml->e);
						}
						else {
							PRINT_ERR("\tLoop %u has invalid edge reference (%u)\n", sp->loopstart + j, ml->e);
							sp->invalid = TRUE;
						}
					}
					else {
						me = &medges[ml->e];
						if (IS_REMOVED_EDGE(me) || !((me->v1 == v1 && me->v2 == v2) || (me->v1 == v2 && me->v2 == v1))) {
							/* The pointed edge is invalid (tagged as removed, or vert idx mismatch),
							 * and we already know from previous test that a valid one exists, use it (if allowed)! */
							if (do_fixes) {
								int prev_e = ml->e;
								ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, v1, v2));
								PRINT_ERR("\tPoly %u has invalid edge reference (%u), fixed using edge %u\n",
								          sp->index, prev_e, ml->e);
							}
							else {
								PRINT_ERR("\tPoly %u has invalid edge reference (%u)\n", sp->index, ml->e);
								sp->invalid = TRUE;
							}
						}
					}
				}

				/* Now check that that poly does not use a same vertex more than once! */
				if (!sp->invalid) {
					int *prev_v = v = sp->verts;
					j = sp->numverts;

					qsort(sp->verts, j, sizeof(int), int_cmp);

					for (j--, v++; j; j--, v++) {
						if (*v != *prev_v) {
							int dlt = v - prev_v;
							if (dlt > 1) {
								PRINT_ERR("\tPoly %u is invalid, it multi-uses vertex %u (%u times)\n",
								          sp->index, *prev_v, dlt);
								sp->invalid = TRUE;
							}
							prev_v = v;
						}
					}
					if (v - prev_v > 1) { /* Don't forget final verts! */
						PRINT_ERR("\tPoly %u is invalid, it multi-uses vertex %u (%u times)\n",
						          sp->index, *prev_v, (int)(v - prev_v));
						sp->invalid = TRUE;
					}
				}
			
			}
		}

		/* Second check pass, testing polys using the same verts. */
		qsort(sort_polys, totpoly, sizeof(SortPoly), search_poly_cmp);
		sp = prev_sp = sort_polys;
		sp++;

		for (i = 1; i < totpoly; i++, sp++) {
			int p1_nv = sp->numverts, p2_nv = prev_sp->numverts;
			int *p1_v = sp->verts, *p2_v = prev_sp->verts;
			short p1_sub = TRUE, p2_sub = TRUE;
			if (sp->invalid)
				break;
			/* Test same polys. */
#if 0
			/* NOTE: This performs a sub-set test. */
			/* XXX This (and the sort of verts list) is better than systematic
			 *     search of all verts of one list into the other if lists have
			 *     a fair amount of elements.
			 *     Not sure however it's worth it in this case?
			 *     But as we also need sorted vert list to check verts multi-used
			 *     (in first pass of checks)... */
			/* XXX If we consider only "equal" polys (i.e. using exactly same set of verts)
			 *     as invalid, better to replace this by a simple memory cmp... */
			while ((p1_nv && p2_nv) && (p1_sub || p2_sub)) {
				if (*p1_v < *p2_v) {
					if (p1_sub)
						p1_sub = FALSE;
					p1_nv--;
					p1_v++;
				}
				else if (*p2_v < *p1_v) {
					if (p2_sub)
						p2_sub = FALSE;
					p2_nv--;
					p2_v++;
				}
				else {
					/* Equality, both next verts. */
					p1_nv--;
					p2_nv--;
					p1_v++;
					p2_v++;
				}
			}
			if (p1_nv && p1_sub)
				p1_sub = FALSE;
			else if (p2_nv && p2_sub)
				p2_sub = FALSE;

			if (p1_sub && p2_sub) {
				PRINT("\tPolys %u and %u use same vertices, considering poly %u as invalid.\n",
				      prev_sp->index, sp->index, sp->index);
				sp->invalid = TRUE;
			}
			/* XXX In fact, these might be valid? :/ */
			else if (p1_sub) {
				PRINT("\t%u is a sub-poly of %u, considering it as invalid.\n", sp->index, prev_sp->index);
				sp->invalid = TRUE;
			}
			else if (p2_sub) {
				PRINT("\t%u is a sub-poly of %u, considering it as invalid.\n", prev_sp->index, sp->index);
				prev_sp->invalid = TRUE;
				prev_sp = sp; /* sp is new reference poly. */
			}
#else
			if (0) {
				p1_sub += 0;
				p2_sub += 0;
			}
			if ((p1_nv == p2_nv) && (memcmp(p1_v, p2_v, p1_nv * sizeof(*p1_v)) == 0)) {
				if (do_verbose) {
					PRINT_ERR("\tPolys %u and %u use same vertices (%u",
					          prev_sp->index, sp->index, *p1_v);
					for (j = 1; j < p1_nv; j++)
						PRINT_ERR(", %u", p1_v[j]);
					PRINT_ERR("), considering poly %u as invalid.\n", sp->index);
				}
				else {
					is_valid = false;
				}
				sp->invalid = TRUE;
			}
#endif
			else {
				prev_sp = sp;
			}
		}

		/* Third check pass, testing loops used by none or more than one poly. */
		qsort(sort_polys, totpoly, sizeof(SortPoly), search_polyloop_cmp);
		sp = sort_polys;
		prev_sp = NULL;
		prev_end = 0;
		for (i = 0; i < totpoly; i++, sp++) {
			/* Free this now, we don't need it anymore, and avoid us another loop! */
			if (sp->verts)
				MEM_freeN(sp->verts);

			/* Note above prev_sp: in following code, we make sure it is always valid poly (or NULL). */
			if (sp->invalid) {
				if (do_fixes) {
					REMOVE_POLY_TAG((&mpolys[sp->index]));
					/* DO NOT REMOVE ITS LOOPS!!!
					 * As already invalid polys are at the end of the SortPoly list, the loops they
					 * were the only users have already been tagged as "to remove" during previous
					 * iterations, and we don't want to remove some loops that may be used by
					 * another valid poly! */
				}
			}
			/* Test loops users. */
			else {
				/* Unused loops. */
				if (prev_end < sp->loopstart) {
					for (j = prev_end, ml = &mloops[prev_end]; j < sp->loopstart; j++, ml++) {
						PRINT_ERR("\tLoop %u is unused.\n", j);
						if (do_fixes)
							REMOVE_LOOP_TAG(ml);
					}
					prev_end = sp->loopstart + sp->numverts;
					prev_sp = sp;
				}
				/* Multi-used loops. */
				else if (prev_end > sp->loopstart) {
					PRINT_ERR("\tPolys %u and %u share loops from %u to %u, considering poly %u as invalid.\n",
					          prev_sp->index, sp->index, sp->loopstart, prev_end, sp->index);
					if (do_fixes) {
						REMOVE_POLY_TAG((&mpolys[sp->index]));
						/* DO NOT REMOVE ITS LOOPS!!!
						 * They might be used by some next, valid poly!
						 * Just not updating prev_end/prev_sp vars is enough to ensure the loops
						 * effectively no more needed will be marked as "to be removed"! */
					}
				}
				else {
					prev_end = sp->loopstart + sp->numverts;
					prev_sp = sp;
				}
			}
		}
		/* We may have some remaining unused loops to get rid of! */
		if (prev_end < totloop) {
			for (j = prev_end, ml = &mloops[prev_end]; j < totloop; j++, ml++) {
				PRINT_ERR("\tLoop %u is unused.\n", j);
				if (do_fixes)
					REMOVE_LOOP_TAG(ml);
			}
		}

		MEM_freeN(sort_polys);
	}

	BLI_edgehash_free(edge_hash, NULL);

	/* fix deform verts */
	if (dverts) {
		MDeformVert *dv;
		for (i = 0, dv = dverts; i < totvert; i++, dv++) {
			MDeformWeight *dw;

			for (j = 0, dw = dv->dw; j < dv->totweight; j++, dw++) {
				/* note, greater then max defgroups is accounted for in our code, but not < 0 */
				if (!finite(dw->weight)) {
					PRINT_ERR("\tVertex deform %u, group %d has weight: %f\n", i, dw->def_nr, dw->weight);
					if (do_fixes) {
						dw->weight = 0.0f;
						vert_weights_fixed = TRUE;
					}
				}
				else if (dw->weight < 0.0f || dw->weight > 1.0f) {
					PRINT_ERR("\tVertex deform %u, group %d has weight: %f\n", i, dw->def_nr, dw->weight);
					if (do_fixes) {
						CLAMP(dw->weight, 0.0f, 1.0f);
						vert_weights_fixed = TRUE;
					}
				}

				if (dw->def_nr < 0) {
					PRINT_ERR("\tVertex deform %u, has invalid group %d\n", i, dw->def_nr);
					if (do_fixes) {
						defvert_remove_group(dv, dw);
						if (dv->dw) {
							/* re-allocated, the new values compensate for stepping
							 * within the for loop and may not be valid */
							j--;
							dw = dv->dw + j;

							vert_weights_fixed = TRUE;
						}
						else { /* all freed */
							break;
						}
					}
				}
			}
		}
	}

#   undef REMOVE_EDGE_TAG
#   undef IS_REMOVED_EDGE
#   undef REMOVE_LOOP_TAG
#   undef REMOVE_POLY_TAG

	if (mesh) {
		if (do_face_free) {
			BKE_mesh_strip_loose_faces(mesh);
		}

		if (do_polyloop_free) {
			BKE_mesh_strip_loose_polysloops(mesh);
		}

		if (do_edge_free) {
			BKE_mesh_strip_loose_edges(mesh);
		}

		if (do_edge_recalc) {
			BKE_mesh_calc_edges(mesh, true, false);
		}
	}

	if (mesh && mesh->mselect) {
		MSelect *msel;
		int free_msel = FALSE;

		for (i = 0, msel = mesh->mselect; i < mesh->totselect; i++, msel++) {
			int tot_elem = 0;

			if (msel->index < 0) {
				PRINT_ERR("\tMesh select element %d type %d index is negative, "
				          "resetting selection stack.\n", i, msel->type);
				free_msel = TRUE;
				break;
			}

			switch (msel->type) {
				case ME_VSEL:
					tot_elem = mesh->totvert;
					break;
				case ME_ESEL:
					tot_elem = mesh->totedge;
					break;
				case ME_FSEL:
					tot_elem = mesh->totface;
					break;
			}

			if (msel->index > tot_elem) {
				PRINT_ERR("\tMesh select element %d type %d index %d is larger than data array size %d, "
				          "resetting selection stack.\n", i, msel->type, msel->index, tot_elem);

				free_msel = TRUE;
				break;
			}
		}

		if (free_msel) {
			MEM_freeN(mesh->mselect);
			mesh->mselect = NULL;
			mesh->totselect = 0;
		}
	}

	PRINT_MSG("%s: finished\n\n", __func__);

	*r_change = (verts_fixed || vert_weights_fixed || do_polyloop_free || do_edge_free || do_edge_recalc || msel_fixed);

	return is_valid;
}
Ejemplo n.º 18
0
void XInputUtils::fixXInputCoords(GdkEvent* event, GtkWidget* widget)
{
	double* axes, *px, *py;
	GdkDevice* device;
	int wx, wy, ix, iy;

	if (event->type == GDK_BUTTON_PRESS || event->type == GDK_BUTTON_RELEASE)
	{
		axes = event->button.axes;
		px = &(event->button.x);
		py = &(event->button.y);
		device = event->button.device;
	}
	else if (event->type == GDK_MOTION_NOTIFY)
	{
		axes = event->motion.axes;
		px = &(event->motion.x);
		py = &(event->motion.y);
		device = event->motion.device;
	}
	else
	{
		return; // nothing we know how to do
	}

	if (axes == NULL)
	{
		return;
	}

#ifdef ENABLE_XINPUT_BUGFIX
	// fix broken events with the core pointer's location
	if (!finite(axes[0]) || !finite(axes[1]) || (axes[0] == 0. && axes[1] == 0.))
	{
		gdk_window_get_pointer(GTK_WIDGET(widget)->window, &ix, &iy, NULL);
		*px = ix;
		*py = iy;
	}
	else
	{
		gdk_window_get_origin(GTK_WIDGET(widget)->window, &wx, &wy);
		double axis_width = device->axes[0].max - device->axes[0].min;
		if (axis_width > EPSILON)
		{
			*px = (axes[0] / axis_width) * screenWidth - wx;
		}
		axis_width = device->axes[1].max - device->axes[1].min;
		if (axis_width > EPSILON)
		{
			*py = (axes[1] / axis_width) * screenHeight - wy;
		}
	}
#else
	if (!finite(*px) || !finite(*py) || (*px == 0. && *py == 0.))
	{
		gdk_window_get_pointer(GTK_WIDGET(widget)->window, &ix, &iy, NULL);
		*px = ix;
		*py = iy;
	}
	else
	{
		/* with GTK+ 2.17, events come improperly translated, and the event's
		 GdkWindow isn't even the same for ButtonDown as for MotionNotify... */
		if (gtk_major_version == 2 && gtk_minor_version == 17)   // GTK+ 2.17 issues !!
		{
			gdk_window_get_position(GTK_WIDGET(widget)->window, &wx, &wy);
			*px += wx;
			*py += wy;
		}
	}
#endif
}
Ejemplo n.º 19
0
static DerivedMesh *doOcean(ModifierData *md, Object *ob,
                            DerivedMesh *derivedData,
                            int UNUSED(useRenderParams))
{
	OceanModifierData *omd = (OceanModifierData *) md;

	DerivedMesh *dm = NULL;
	OceanResult ocr;

	MVert *mverts, *mv;
	MLoop *mloops;

	int i, j;

	int num_verts;
	int num_faces;

	int cfra;

	/* use cached & inverted value for speed
	 * expanded this would read...
	 *
	 * (axis / (omd->size * omd->spatial_size)) + 0.5f) */
#define OCEAN_CO(_size_co_inv, _v) ((_v * _size_co_inv) + 0.5f)

	const float size_co_inv = 1.0f / (omd->size * omd->spatial_size);

	/* can happen in when size is small, avoid bad array lookups later and quit now */
	if (!finite(size_co_inv)) {
		return derivedData;
	}

	/* update modifier */
	if (omd->refresh & MOD_OCEAN_REFRESH_ADD)
		omd->ocean = BKE_add_ocean();
	if (omd->refresh & MOD_OCEAN_REFRESH_RESET)
		init_ocean_modifier(omd);
	if (omd->refresh & MOD_OCEAN_REFRESH_CLEAR_CACHE)
		clear_cache_data(omd);

	omd->refresh = 0;

	/* do ocean simulation */
	if (omd->cached == TRUE) {
		if (!omd->oceancache) init_cache_data(ob, omd);
		BKE_simulate_ocean_cache(omd->oceancache, md->scene->r.cfra);
	}
	else {
		simulate_ocean_modifier(omd);
	}

	if (omd->geometry_mode == MOD_OCEAN_GEOM_GENERATE) {
		dm = generate_ocean_geometry(omd);
		DM_ensure_normals(dm);
	}
	else if (omd->geometry_mode == MOD_OCEAN_GEOM_DISPLACE) {
		dm = CDDM_copy(derivedData);
	}

	cfra = md->scene->r.cfra;
	CLAMP(cfra, omd->bakestart, omd->bakeend);
	cfra -= omd->bakestart; /* shift to 0 based */

	num_verts = dm->getNumVerts(dm);
	num_faces = dm->getNumPolys(dm);

	mverts = dm->getVertArray(dm);
	mloops = dm->getLoopArray(dm);

	/* add vcols before displacement - allows lookup based on position */

	if (omd->flag & MOD_OCEAN_GENERATE_FOAM) {
		int cdlayer = CustomData_number_of_layers(&dm->loopData, CD_MLOOPCOL);

		if (cdlayer < MAX_MCOL) {
			MLoopCol *mloopcols = CustomData_add_layer_named(&dm->loopData, CD_MLOOPCOL, CD_CALLOC, NULL,
			                                                 num_faces * 4, omd->foamlayername);

			if (mloopcols) { /* unlikely to fail */
				MLoopCol *mlcol;
				MPoly *mpolys = dm->getPolyArray(dm);
				MPoly *mp;

				float foam;

				for (i = 0, mp = mpolys; i < num_faces; i++, mp++) {
					j = mp->totloop - 1;

					/* highly unlikely */
					if (j <= 0) continue;

					do {
						const float *co = mverts[mloops[mp->loopstart + j].v].co;
						const float u = OCEAN_CO(size_co_inv, co[0]);
						const float v = OCEAN_CO(size_co_inv, co[1]);

						if (omd->oceancache && omd->cached == TRUE) {
							BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v);
							foam = ocr.foam;
							CLAMP(foam, 0.0f, 1.0f);
						}
						else {
							BKE_ocean_eval_uv(omd->ocean, &ocr, u, v);
							foam = BKE_ocean_jminus_to_foam(ocr.Jminus, omd->foam_coverage);
						}

						mlcol = &mloopcols[mp->loopstart + j];
						mlcol->r = mlcol->g = mlcol->b = (char)(foam * 255);
						/* This needs to be set (render engine uses) */
						mlcol->a = 255;
					} while (j--);
				}
			}
		}
	}


	/* displace the geometry */

	/* #pragma omp parallel for private(i, ocr) if (omd->resolution > OMP_MIN_RES) */
	for (i = 0, mv = mverts; i < num_verts; i++, mv++) {
		const float u = OCEAN_CO(size_co_inv, mv->co[0]);
		const float v = OCEAN_CO(size_co_inv, mv->co[1]);

		if (omd->oceancache && omd->cached == TRUE)
			BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v);
		else
			BKE_ocean_eval_uv(omd->ocean, &ocr, u, v);

		mv->co[2] += ocr.disp[1];

		if (omd->chop_amount > 0.0f) {
			mv->co[0] += ocr.disp[0];
			mv->co[1] += ocr.disp[2];
		}
	}

#undef OCEAN_CO

	return dm;
}
Ejemplo n.º 20
0
/** Calculate a bounding box for a set of bezier points.
 * @param pts The bezier points
 * @param numpoints The number of elements in `pts'
 * @param extra Extra spacing information.
 * @param closed True if the bezier points form a closed line.
 * @param rect Return value: The enclosing rectangle will be stored here.
 * @bug This function is way too long (214 lines) and should be split.
 */
void 
polybezier_bbox(const BezPoint *pts, int numpoints,
                const PolyBBExtras *extra, gboolean closed,            
                Rectangle *rect)
{
  Point vx,vn,vsc,vp;
  int i,prev,next;
  Rectangle rt;
  PolyBBExtras bextra,start_bextra,end_bextra;
  LineBBExtras lextra,start_lextra,end_lextra,full_lextra;
  gboolean start,end;

  vp.x=0;
  vp.y=0;

  g_assert(pts[0].type == BEZ_MOVE_TO);

  rect->left = rect->right = pts[0].p1.x;
  rect->top = rect->bottom = pts[0].p1.y;

  /* First, we build derived BBExtras structures, so we have something to feed 
     the primitives. */ 
  if (!closed) {
    start_lextra.start_long = extra->start_long;
    start_lextra.start_trans = MAX(extra->start_trans,extra->middle_trans);
    start_lextra.end_long = 0;
    start_lextra.end_trans = extra->middle_trans;

    end_lextra.start_long = 0;
    end_lextra.start_trans = extra->middle_trans;
    end_lextra.end_long = extra->end_long;
    end_lextra.end_trans = MAX(extra->end_trans,extra->middle_trans);
  }

  full_lextra.start_long = extra->start_long;
  full_lextra.start_trans = MAX(extra->start_trans,extra->middle_trans);
  full_lextra.end_long = extra->end_long;
  full_lextra.end_trans = MAX(extra->end_trans,extra->middle_trans);

  if (!closed) {
    lextra.start_long = 0;
    lextra.start_trans = extra->middle_trans;
    lextra.end_long = 0;
    lextra.end_trans = extra->middle_trans;

    start_bextra.start_long = extra->start_long;
    start_bextra.start_trans = extra->start_trans;
    start_bextra.middle_trans = extra->middle_trans;
    start_bextra.end_long = 0;
    start_bextra.end_trans = extra->middle_trans;

    end_bextra.start_long = 0;
    end_bextra.start_trans = extra->middle_trans;
    end_bextra.middle_trans = extra->middle_trans;
    end_bextra.end_long = extra->end_long;
    end_bextra.end_trans = extra->end_trans;
  }

  bextra.start_long = 0;
  bextra.start_trans = extra->middle_trans;
  bextra.middle_trans = extra->middle_trans;
  bextra.end_long = 0;
  bextra.end_trans = extra->middle_trans;        


  for (i=1;i<numpoints;i++) {
    next = (i+1) % numpoints;
    prev = (i-1) % numpoints;
    if (closed && (next == 0)) next=1;
    if (closed && (prev == 0)) prev=numpoints-1;

    /* We have now: 
       i = index of current vertex. 
       prev,next: index of previous/next vertices (of the control polygon) 

       We want:
        vp, vx, vn: the previous, current and next vertices;
        start, end: TRUE if we're at an end of poly (then, vp and/or vn are not
        valid, respectively).

       Some values *will* be recomputed a few times across iterations (but stored in 
       different boxes). Either gprof says it's a real problem, or gcc finally gets 
       a clue.
    */

    if (pts[i].type == BEZ_MOVE_TO) {
      continue;
    }

    switch(pts[i].type) {
    case BEZ_MOVE_TO:
      g_assert_not_reached();
      break;
    case BEZ_LINE_TO:
      point_copy(&vx,&pts[i].p1);
      switch(pts[prev].type) {
      case BEZ_MOVE_TO:
      case BEZ_LINE_TO:
        point_copy(&vsc,&pts[prev].p1);
        point_copy(&vp,&pts[prev].p1);
        break;
      case BEZ_CURVE_TO:
        point_copy(&vsc,&pts[prev].p3);
        point_copy(&vp,&pts[prev].p3);
        break;
      }
      break;
    case BEZ_CURVE_TO:
      point_copy(&vx,&pts[i].p3);
      point_copy(&vp,&pts[i].p2);
      switch(pts[prev].type) {
      case BEZ_MOVE_TO:
      case BEZ_LINE_TO:
        point_copy(&vsc,&pts[prev].p1);
        break;
      case BEZ_CURVE_TO:
        point_copy(&vsc,&pts[prev].p3);
        break;
      } /* vsc is the start of the curve. */
      
      break;
    }
    start = (pts[prev].type == BEZ_MOVE_TO);
    end = (pts[next].type == BEZ_MOVE_TO);
    point_copy(&vn,&pts[next].p1); /* whichever type pts[next] is. */

    /* Now, we know about a few vertices around the one we're dealing with.
       Depending on the shape of the (previous,current) segment, and whether 
       it's a middle or end segment, we'll be doing different stuff. */ 
    if (closed) {
      if (pts[i].type == BEZ_LINE_TO) {
        line_bbox(&vsc,&vx,&full_lextra,&rt);
      } else {
        bicubicbezier2D_bbox(&vsc,
                             &pts[i].p1,&pts[i].p2,&pts[i].p3,
                             &bextra,
                             &rt);
      }    
    } else if (start) {
      if (pts[i].type == BEZ_LINE_TO) {
        if (end) {
          line_bbox(&vsc,&vx,&full_lextra,&rt);
        } else {
          line_bbox(&vsc,&vx,&start_lextra,&rt);
        }
      } else { /* BEZ_MOVE_TO */ 
        if (end) {
          bicubicbezier2D_bbox(&vsc,
                               &pts[i].p1,&pts[i].p2,&pts[i].p3,
                               extra,
                               &rt);
        } else {
          bicubicbezier2D_bbox(&vsc,
                               &pts[i].p1,&pts[i].p2,&pts[i].p3,
                               &start_bextra,
                               &rt);
        }
      }
    } else if (end) { /* end but not start. Not closed anyway. */
      if (pts[i].type == BEZ_LINE_TO) {
        line_bbox(&vsc,&vx,&end_lextra,&rt);
      } else {
        bicubicbezier2D_bbox(&vsc,
                             &pts[i].p1,&pts[i].p2,&pts[i].p3,
                             &end_bextra,
                             &rt);
      } 
    } else { /* normal case : middle segment (not closed shape). */
      if (pts[i].type == BEZ_LINE_TO) {
        line_bbox(&vsc,&vx,&lextra,&rt);
      } else {
        bicubicbezier2D_bbox(&vsc,
                             &pts[i].p1,&pts[i].p2,&pts[i].p3,
                             &bextra,
                             &rt);
      } 
    }   
    rectangle_union(rect,&rt);

    /* The following code enlarges a little the bounding box (if necessary) to 
       account with the "pointy corners" X (and PS) add when LINEJOIN_MITER mode is 
       in force. */

    if ((!start) && (!end)) { /* We have a non-extremity vertex. */
      Point vpx,vxn;
      real co,alpha;

      point_copy_add_scaled(&vpx,&vx,&vp,-1);
      point_normalize(&vpx);
      point_copy_add_scaled(&vxn,&vn,&vx,-1);
      point_normalize(&vxn);

      co = point_dot(&vpx,&vxn);      
      alpha = acos(-co); 
      if (co > -0.9816) { /* 0.9816 = cos(11deg) */
        /* we have a pointy join. */
        real overshoot;
        Point vovs,pto;

	if (finite(alpha))
	  overshoot = extra->middle_trans / sin(alpha/2.0);
	else /* prependicular? */
	  overshoot = extra->middle_trans;

        point_copy_add_scaled(&vovs,&vpx,&vxn,-1);
        point_normalize(&vovs);
        point_copy_add_scaled(&pto,&vx,&vovs,overshoot);
        
        rectangle_add_point(rect,&pto);
      } else {
        /* we don't have a pointy join. */
        Point vpxt,vxnt,tmp;

        point_get_perp(&vpxt,&vpx);
        point_get_perp(&vxnt,&vxn);
        
        point_copy_add_scaled(&tmp,&vx,&vpxt,1);
        rectangle_add_point(rect,&tmp);
        point_copy_add_scaled(&tmp,&vx,&vpxt,-1);
        rectangle_add_point(rect,&tmp);
        point_copy_add_scaled(&tmp,&vx,&vxnt,1);
        rectangle_add_point(rect,&tmp);
        point_copy_add_scaled(&tmp,&vx,&vxnt,-1);
        rectangle_add_point(rect,&tmp);
      }
    }
  }
}
Ejemplo n.º 21
0
void Linearizer::process_triangle(int iv0, int iv1, int iv2, int level,
                                  scalar* val, double* phx, double* phy, int* idx)
{
  double midval[3][3];

  if (level < LIN_MAX_LEVEL)
  {
    int i;
    if (!(level & 1))
    {
      // obtain solution values
      sln->set_quad_order(1, item);
      val = sln->get_values(ia, ib);
      if (auto_max)
        for (i = 0; i < lin_np_tri[1]; i++) {
          double v = getval(i);
          if (finite(v) && fabs(v) > max) max = fabs(v);
        }

      // obtain physical element coordinates
      if (curved || disp)
      {
        RefMap* refmap = sln->get_refmap();
        phx = refmap->get_phys_x(1);
        phy = refmap->get_phys_y(1);

        if (disp)
        {
          xdisp->force_transform(sln);
          ydisp->force_transform(sln);
          xdisp->set_quad_order(1, FN_VAL);
          ydisp->set_quad_order(1, FN_VAL);
          scalar* dx = xdisp->get_fn_values();
          scalar* dy = ydisp->get_fn_values();
          for (i = 0; i < lin_np_tri[1]; i++) {
            phx[i] += dmult*realpart(dx[i]);
            phy[i] += dmult*realpart(dy[i]);
          }
        }
      }
      idx = tri_indices[0];
    }

    // obtain linearized values and coordinates at the midpoints
    for (i = 0; i < 3; i++)
    {
      midval[i][0] = (verts[iv0][i] + verts[iv1][i])*0.5;
      midval[i][1] = (verts[iv1][i] + verts[iv2][i])*0.5;
      midval[i][2] = (verts[iv2][i] + verts[iv0][i])*0.5;
    };

    // determine whether or not to split the element
    bool split;
    if (eps >= 1.0)
    {
      // if eps > 1, the user wants a fixed number of refinements (no adaptivity)
      split = (level < eps);
    }
    else
    {
      if (!auto_max && fabs(verts[iv0][2]) > max && fabs(verts[iv1][2]) > max && fabs(verts[iv2][2]) > max)
      {
        // do not split if the whole triangle is above the specified maximum value
        split = false;
      }
      else
      {
        // calculate the approximate error of linearizing the normalized solution
        double err = fabs(getval(idx[0]) - midval[2][0]) +
                     fabs(getval(idx[1]) - midval[2][1]) +
                     fabs(getval(idx[2]) - midval[2][2]);
        split = !finite(err) || err > max*3*eps;
      }

      // do the same for the curvature
      if (!split && (curved || disp))
      {
        for (i = 0; i < 3; i++)
          if (sqr(phx[idx[i]] - midval[0][i]) + sqr(phy[idx[i]] - midval[1][i]) > sqr(cmax*1.5e-3))
            { split = true; break; }
      }

      // do extra tests at level 0, so as not to miss some functions with zero error at edge midpoints
      if (level == 0 && !split)
      {
        split = (fabs(getval(8) - 0.5*(midval[2][0] + midval[2][1])) +
                 fabs(getval(9) - 0.5*(midval[2][1] + midval[2][2])) +
                 fabs(getval(4) - 0.5*(midval[2][2] + midval[2][0]))) > max*3*eps;
      }
    }

    // split the triangle if the error is too large, otherwise produce a linear triangle
    if (split)
    {
      if (curved || disp)
        for (i = 0; i < 3; i++) {
          midval[0][i] = phx[idx[i]];
          midval[1][i] = phy[idx[i]];
        }

      // obtain mid-edge vertices
      int mid0 = get_vertex(iv0, iv1, midval[0][0], midval[1][0], getval(idx[0]));
      int mid1 = get_vertex(iv1, iv2, midval[0][1], midval[1][1], getval(idx[1]));
      int mid2 = get_vertex(iv2, iv0, midval[0][2], midval[1][2], getval(idx[2]));

      // recur to sub-elements
      sln->push_transform(0);  process_triangle(iv0, mid0, mid2,  level+1, val, phx, phy, tri_indices[1]);  sln->pop_transform();
      sln->push_transform(1);  process_triangle(mid0, iv1, mid1,  level+1, val, phx, phy, tri_indices[2]);  sln->pop_transform();
      sln->push_transform(2);  process_triangle(mid2, mid1, iv2,  level+1, val, phx, phy, tri_indices[3]);  sln->pop_transform();
      sln->push_transform(3);  process_triangle(mid1, mid2, mid0, level+1, val, phx, phy, tri_indices[4]);  sln->pop_transform();
      return;
    }
  }

  // no splitting: output a linear triangle
  add_triangle(iv0, iv1, iv2);
}
Ejemplo n.º 22
0
Archivo: port.c Proyecto: smunix/ldc
int Port::isFinite(double r)
{
    return finite(r);
}
Ejemplo n.º 23
0
void Linearizer::process_solution(MeshFunction* sln, int item, double eps, double max_abs,
                                  MeshFunction* xdisp, MeshFunction* ydisp, double dmult)
{
  lock_data();
  begin_time();

  // initialization
  this->sln = sln;
  this->item = item;
  this->eps = eps;
  this->xdisp = xdisp;
  this->ydisp = ydisp;
  this->dmult = dmult;
  nv = nt = ne = 0;
  del_slot = -1;

  if (!item) error("'item' cannot be zero.");
  get_gv_a_b(item, ia, ib);
  if (ib >= 6) error("Invalid 'item'.");

  disp = (xdisp != NULL || ydisp != NULL);
  if (disp && (xdisp == NULL || ydisp == NULL))
    error("Both displacement components must be supplied.");

  // estimate the required number of vertices and triangles
  Mesh* mesh = sln->get_mesh();
  int nn = mesh->get_num_elements();
  int ev = std::max(32 * nn, 10000);  // todo: check this
  int et = std::max(64 * nn, 20000);
  int ee = std::max(24 * nn, 7500);

  // check that displacement meshes are the same
  if (disp)
  {
    unsigned seq1 = mesh->get_seq();
    unsigned seq2 = xdisp->get_mesh()->get_seq();
    unsigned seq3 = ydisp->get_mesh()->get_seq();
    if (seq1 != seq2 || seq1 != seq3)
      error("Displacements must be defined on the same mesh as the solution.");
  }

  // reuse or allocate vertex, triangle and edge arrays
  lin_init_array(verts, double3, cv, ev);
  lin_init_array(tris, int3, ct, et);
  lin_init_array(edges, int3, ce, ee);
  info = (int4*) malloc(sizeof(int4) * cv);

  // initialize the hash table
  int size = 0x2000;
  while (size*2 < cv) size *= 2;
  hash_table = (int*) malloc(sizeof(int) * size);
  memset(hash_table, 0xff, sizeof(int) * size);
  mask = size-1;

  // select the linearization quadrature
  Quad2D *old_quad, *old_quad_x, *old_quad_y;
  old_quad = sln->get_quad_2d();
  sln->set_quad_2d(&quad_lin);
  if (disp) { old_quad_x = xdisp->get_quad_2d();
              old_quad_y = ydisp->get_quad_2d();
              xdisp->set_quad_2d(&quad_lin);
              ydisp->set_quad_2d(&quad_lin); }

  // create all top-level vertices (corresponding to vertex nodes), with
  // all parent-son relations preserved; this is necessary for regularization to
  // work on irregular meshes
  nn = mesh->get_max_node_id();
  int* id2id = new int[nn];
  memset(id2id, 0xff, sizeof(int) * nn);
  bool finished;
  do
  {
    finished = true;
    Node* node;
    for_all_vertex_nodes(node, mesh)
    {
      if (id2id[node->id] < 0 && node->ref != TOP_LEVEL_REF)
        if (node->p1 < 0)
          id2id[node->id] = get_vertex(node->id, node->id, node->x, node->y, 0);
        else if (id2id[node->p1] >= 0 && id2id[node->p2] >= 0)
          id2id[node->id] = get_vertex(id2id[node->p1], id2id[node->p2], node->x, node->y, 0);
        else
          finished = false;
    }
  }
  while (!finished);

  auto_max = (max_abs < 0.0);
  max = auto_max ? 0.0 : max_abs;

  // obtain the solution in vertices, estimate the maximum solution value
  Element* e;
  for_all_active_elements(e, mesh)
  {
    sln->set_active_element(e);
    sln->set_quad_order(0, item);
    scalar* val = sln->get_values(ia, ib);
    if (val == NULL) error("item not defined in the solution.");

    scalar *dx, *dy;
    if (disp)
    {
      xdisp->set_active_element(e);
      ydisp->set_active_element(e);
      xdisp->set_quad_order(0, FN_VAL);
      ydisp->set_quad_order(0, FN_VAL);
      dx = xdisp->get_fn_values();
      dy = ydisp->get_fn_values();
    }

    for (unsigned int i = 0; i < e->nvert; i++)
    {
      double f = getval(i);
      if (auto_max && finite(f) && fabs(f) > max) max = fabs(f);
      int id = id2id[e->vn[i]->id];
      verts[id][2] = f;

      if (disp)
      {
        verts[id][0] = e->vn[i]->x + dmult*realpart(dx[i]);
        verts[id][1] = e->vn[i]->y + dmult*realpart(dy[i]);
      }
    }
  }
Ejemplo n.º 24
0
void Vector::internalUpdate() {
  int i, i0;
  double sum, sum2, last, first, v;
  double last_v;
  double dv2 = 0.0, dv, no_spike_max_dv;

  _max = _min = sum = sum2 = _minPos = last = first = NOPOINT;
  _nsum = 0;

  if (_size > 0) {
    _is_rising = true;

    // Look for a valid (finite) point...
    for (i = 0; i < _size && !finite(_v[i]); i++) {
      // do nothing
    }

    if (i == _size) { // there were no finite points:
      if (!_isScalarList) {
        _scalars["sum"]->setValue(sum);
        _scalars["sumsquared"]->setValue(sum2);
        _scalars["max"]->setValue(_max);
        _scalars["min"]->setValue(_min);
        _scalars["minpos"]->setValue(_minPos);
        _scalars["last"]->setValue(last);
        _scalars["first"]->setValue(first);
      }
      _ns_max = _ns_min = 0;

      updateScalars();

      return;
    }

    i0 = i;

    if (i0 > 0) {
      _is_rising = false;
    }

    _max = _min = _v[i0];
    sum = sum2 = 0.0;

    if (_v[i0] > 0.0) {
      _minPos = _v[i0];
    } else {
      _minPos = 1.0E300;
    }

    last_v = _v[i0];

    for (i = i0; i < _size; i++) {
      v = _v[i]; // get rid of redirections

      if (finite(v)) {
        dv = v - last_v;
        dv2 += dv*dv;

        if (v <= last_v) {
          if (i != i0) {
            _is_rising = false;
          }
        }

        last_v = v;

        _nsum++;
        sum += v;
        sum2 += v*v;

        if (v > _max) {
          _max = v;
        } else if (v < _min) {
          _min = v;
        }
        if (v < _minPos && v > 0.0) {
          _minPos = v;
        }
      } else {
        _is_rising = false;
      }
    }

    no_spike_max_dv = 7.0*sqrt(dv2/double(_nsum));

    _ns_max = _ns_min = last_v = _v[i0];

    last = _v[_size-1];
    first = _v[0];

    for (i = i0; i < _size; i++) {
      v = _v[i]; // get rid of redirections
      if (finite(v)) {
        if (fabs(v - last_v) < no_spike_max_dv) {
          if (v > _ns_max) {
            _ns_max = v;
          } else if (v < _ns_min) {
            _ns_min = v;
          }
          last_v = v;
        } else {
          i += 20;
          if (i < _size) {
            last_v = _v[i];
          }
          i++;
        }
      }
    }

    if (_isScalarList) {
      _max = _min = _minPos = 0.0;
    } else {
      _scalars["sum"]->setValue(sum);
      _scalars["sumsquared"]->setValue(sum2);
      _scalars["max"]->setValue(_max);
      _scalars["min"]->setValue(_min);
      _scalars["minpos"]->setValue(_minPos);
      _scalars["last"]->setValue(last);
      _scalars["first"]->setValue(first);
    }

    updateScalars();

  }
}
Ejemplo n.º 25
0
void common_options(int ch)
{
	switch(ch) {
	case 'a':
		options |= F_AUDIBLE;
		break;
	case 'A':
		options |= F_ADAPTIVE;
		break;
	case 'c':
		npackets = atoi(optarg);
		if (npackets <= 0) {
			fprintf(stderr, "ping: bad number of packets to transmit.\n");
			exit(2);
		}
		break;
	case 'd':
		options |= F_SO_DEBUG;
		break;
	case 'D':
		options |= F_PTIMEOFDAY;
		break;
	case 'i':		/* wait between sending packets */
	{
		double dbl;
		char *ep;

		errno = 0;
		dbl = strtod(optarg, &ep);

		if (errno || *ep != '\0' ||
		    !finite(dbl) || dbl < 0.0 || dbl >= (double)INT_MAX / 1000 - 1.0) {
			fprintf(stderr, "ping: bad timing interval\n");
			exit(2);
		}

		interval = (int)(dbl * 1000);

		options |= F_INTERVAL;
		break;
	}
	case 'm':
	{
		char *endp;
		mark = (int)strtoul(optarg, &endp, 10);
		if (mark < 0 || *endp != '\0') {
			fprintf(stderr, "mark cannot be negative\n");
			exit(2);
		}
		options |= F_MARK;
		break;
	}
	case 'w':
		deadline = atoi(optarg);
		if (deadline < 0) {
			fprintf(stderr, "ping: bad wait time.\n");
			exit(2);
		}
		break;
	case 'l':
		preload = atoi(optarg);
		if (preload <= 0) {
			fprintf(stderr, "ping: bad preload value, should be 1..%d\n", MAX_DUP_CHK);
			exit(2);
		}
		if (preload > MAX_DUP_CHK)
			preload = MAX_DUP_CHK;
		if (uid && preload > 3) {
			fprintf(stderr, "ping: cannot set preload to value > 3\n");
			exit(2);
		}
		break;
	case 'O':
		options |= F_OUTSTANDING;
		break;
	case 'S':
		sndbuf = atoi(optarg);
		if (sndbuf <= 0) {
			fprintf(stderr, "ping: bad sndbuf value.\n");
			exit(2);
		}
		break;
	case 'f':
		options |= F_FLOOD;
		setbuf(stdout, (char *)NULL);
		/* fallthrough to numeric - avoid gethostbyaddr during flood */
	case 'n':
		options |= F_NUMERIC;
		break;
	case 'p':		/* fill buffer with user pattern */
		options |= F_PINGFILLED;
		fill(optarg);
		break;
	case 'q':
		options |= F_QUIET;
		break;
	case 'r':
		options |= F_SO_DONTROUTE;
		break;
	case 's':		/* size of packet to send */
		datalen = atoi(optarg);
		if (datalen < 0) {
			fprintf(stderr, "ping: illegal negative packet size %d.\n", datalen);
			exit(2);
		}
		if (datalen > maxpacket - 8) {
			fprintf(stderr, "ping: packet size too large: %d\n",
				datalen);
			exit(2);
		}
		break;
	case 'v':
		options |= F_VERBOSE;
		break;
	case 'L':
		options |= F_NOLOOP;
		break;
	case 't':
		options |= F_TTL;
		ttl = atoi(optarg);
		if (ttl < 0 || ttl > 255) {
			fprintf(stderr, "ping: ttl %u out of range\n", ttl);
			exit(2);
		}
		break;
	case 'U':
		options |= F_LATENCY;
		break;
	case 'B':
		options |= F_STRICTSOURCE;
		break;
	case 'W':
		lingertime = atoi(optarg);
		if (lingertime < 0 || lingertime > INT_MAX/1000000) {
			fprintf(stderr, "ping: bad linger time.\n");
			exit(2);
		}
		lingertime *= 1000;
		break;
	case 'V':
		printf("ping utility, iputils-%s\n", SNAPSHOT);
		exit(0);
	default:
		abort();
	}
}
Ejemplo n.º 26
0
static DataType collator_is_numeric(UChar *str, int length, int64_t *lval,
                                    double *dval, int allow_errors ) {
  int64_t local_lval;
  double local_dval;
  UChar *end_ptr_long, *end_ptr_double;
  int conv_base=10;

  if (!length) {
    return KindOfNull;
  }

  /* handle hex numbers */
  if (length>=2 && str[0]=='0' && (str[1]=='x' || str[1]=='X')) {
    conv_base=16;
  }

  errno=0;
  local_lval = collator_u_strtol(str, &end_ptr_long, conv_base);
  if (errno != ERANGE) {
    if (end_ptr_long == str+length) { /* integer string */
      if (lval) {
        *lval = local_lval;
      }
      return KindOfInt64;
    } else if (end_ptr_long == str &&
               *end_ptr_long != '\0' &&
               *str != '.' &&
               *str != '-') { /* ignore partial string matches */
      return KindOfNull;
    }
  } else {
    end_ptr_long = nullptr;
  }

  if (conv_base == 16) { /* hex string, under UNIX strtod() messes it up */
    /* UTODO: keep compatibility with is_numeric_string() here? */
    return KindOfNull;
  }

  local_dval = collator_u_strtod(str, &end_ptr_double);
  if (local_dval == 0 && end_ptr_double == str) {
    end_ptr_double = nullptr;
  } else {
    if (end_ptr_double == str+length) { /* floating point string */
      if (!finite(local_dval)) {
        /* "inf","nan" and maybe other weird ones */
        return KindOfNull;
      }

      if (dval) {
        *dval = local_dval;
      }
      return KindOfDouble;
    }
  }

  if (!allow_errors) {
    return KindOfNull;
  }
  if (allow_errors == -1) {
    raise_notice("A non well formed numeric value encountered");
  }

  if (allow_errors) {
    if (end_ptr_double > end_ptr_long && dval) {
      *dval = local_dval;
      return KindOfDouble;
    } else if (end_ptr_long && lval) {
      *lval = local_lval;
      return KindOfInt64;
    }
  }
  return KindOfNull;
}
Ejemplo n.º 27
0
int
main(int argc, char *argv[]) {
  char   **av, fname[STRLEN] ;
  int    ac, nargs, i ;
  MRI    *mri_flash[MAX_IMAGES], *mri_T1, *mri_PD ;
  char   *in_fname, *out_PD_fname, *out_T1_fname ;
  int          msec, minutes, seconds, nvolumes ;
  struct timeb start ;

  /* rkt: check for and handle version tag */
  nargs = handle_version_option (argc, argv, "$Id: mri_estimate_tissue_parms.c,v 1.9 2011/03/02 00:04:15 nicks Exp $", "$Name:  $");
  if (nargs && argc - nargs == 1)
    exit (0);
  argc -= nargs;

  Progname = argv[0] ;
  ErrorInit(NULL, NULL, NULL) ;
  DiagInit(NULL, NULL, NULL) ;

  TimerStart(&start) ;
  parms.dt = 1e-6 ;
  parms.tol = 1e-5 ;
  parms.momentum = 0.0 ;
  parms.niterations = 20 ;

  ac = argc ;
  av = argv ;
  for ( ; argc > 1 && ISOPTION(*argv[1]) ; argc--, argv++) {
    nargs = get_option(argc, argv) ;
    argc -= nargs ;
    argv += nargs ;
  }

  if (argc < 4)
    usage_exit(1) ;

  out_T1_fname = argv[argc-2] ;
  out_PD_fname = argv[argc-1] ;
  FileNameOnly(out_T1_fname, fname) ;
  FileNameRemoveExtension(fname, fname) ;
  strcpy(parms.base_name, fname) ;

  nvolumes = 0 ;
  for (i = 1 ; i < argc-2 ; i++) {
    if (argv[i][0] == '-') {
      if (!stricmp(argv[i]+1, "te"))
        te = atof(argv[i+1]) ;
      else if (!stricmp(argv[i]+1, "tr"))
        tr = atof(argv[i+1]) ;
      else if (!stricmp(argv[i]+1, "fa"))
        fa = RADIANS(atof(argv[i+1])) ;
      else
        ErrorExit(ERROR_BADPARM, "%s: unsupported MR parameter %s",
                  Progname, argv[i]+1) ;
      i++ ;  /* skip parameter */
      continue ;
    }

    in_fname = argv[i] ;
    printf("reading %s...", in_fname) ;

    mri_flash[nvolumes] = MRIread(in_fname) ;
    if (!mri_flash[nvolumes])
      ErrorExit(Gerror, "%s: MRIread(%s) failed", Progname, in_fname) ;
    if (tr > 0) {
      mri_flash[nvolumes]->tr = tr ;
      tr = 0 ;
    }
    if (te > 0) {
      mri_flash[nvolumes]->te = te ;
      te = 0 ;
    }
    if (fa > 0) {
      mri_flash[nvolumes]->flip_angle = fa ;
      fa = 0 ;
    }
    printf("TE = %2.2f, TR = %2.2f, alpha = %2.2f\n", mri_flash[nvolumes]->te,
           mri_flash[nvolumes]->tr, DEGREES(mri_flash[nvolumes]->flip_angle)) ;
    mri_flash[nvolumes]->flip_angle = mri_flash[nvolumes]->flip_angle;
    if (conform) {
      MRI *mri_tmp ;

      printf("embedding and interpolating volume\n") ;
      mri_tmp = MRIconform(mri_flash[nvolumes]) ;
      /*      MRIfree(&mri_src) ;*/
      mri_flash[nvolumes] = mri_tmp ;
    }
    if (FZERO(mri_flash[nvolumes]->tr) ||
        FZERO(mri_flash[nvolumes]->flip_angle))
      ErrorExit(ERROR_BADPARM, "%s: invalid TR or FA for image %d:%s",
                Progname, nvolumes, in_fname) ;
    nvolumes++ ;
  }
  printf("using %d FLASH volumes to estimate tissue parameters.\n", nvolumes) ;
  mri_T1 = MRIclone(mri_flash[0], NULL) ;
  mri_PD = MRIclone(mri_flash[0], NULL) ;


  {
    double   sse, last_T1, last_PD, total_rms, avg_rms ;
    int      x, y, z, width, height, depth, total_vox, ignored, nvox ;
    struct timeb first_slice ;

    Progname = argv[0] ;
    ErrorInit(NULL, NULL, NULL) ;
    DiagInit(NULL, NULL, NULL) ;

    TimerStart(&first_slice) ;

    last_T1 = last_PD = 1000 ;
    sse = 0.0 ;
    width = mri_T1->width ;
    height = mri_T1->height ;
    depth = mri_T1->depth ;
    total_vox = width*depth*height ;
#if 0
    estimateVoxelParameters(mri_flash, nvolumes, width/2, height/2, depth/2,
                            mri_T1, mri_PD, last_T1, last_PD) ;
#endif
    if (Gdiag_no == 999) {
      x = 130 ;
      y = 124 ;
      z = 74 ; /* CSF */
      computeErrorSurface("error_surf_csf.dat",mri_flash,nvolumes,x,y,z,500,3000,500,3000);
      x = 161 ;
      y = 157 ;
      z = 63 ;  /* wm */
      computeErrorSurface("error_surf_wm.dat",mri_flash,nvolumes,x,y,z,250,3000,250,3000);
      x = 166 ;
      y = 153 ;
      z = 63 ;  /* gm */
      computeErrorSurface("error_surf_gm.dat",mri_flash,nvolumes,x,y,z,250,3000,250,3000);
    }
    avg_rms = 0 ;
    for (ignored = z = 0 ; z < depth ; z++) {
      if (z > 0)
        printf("z = %d, avg rms=%2.1f, T1=%2.0f, PD=%2.0f...\n",
               z, avg_rms, last_T1, last_PD) ;
#if 0
      if (z > 0 && z*width*height - ignored > 0) {
        int processed = z*width*height - ignored, hours ;

        msec = TimerStop(&first_slice) ;
        seconds = nint((float)msec/1000.0f) ;
        minutes = seconds / 60 ;
        seconds = seconds % 60 ;
        hours = minutes / 60 ;
        minutes = minutes % 60 ;
        printf("%02d:%02d:%02d total processing time ... ",
               hours,minutes,seconds);
        msec = (int)((float)(total_vox-ignored)*msec/(float)processed) ;
        seconds = nint((float)msec/1000.0f) ;
        minutes = seconds / 60 ;
        seconds = seconds % 60 ;
        hours = minutes / 60 ;
        minutes = minutes % 60 ;
        printf("estimate %02d:%02d:%02d remaining.\n", hours,minutes, seconds);
      }
#endif
      if (write_iterations > 0 && z > 0 && !(z%write_iterations)) {
        printf("writing T1 esimates to %s...\n", out_T1_fname) ;
        printf("writing PD estimates to %s...\n", out_PD_fname) ;
        MRIwrite(mri_T1, out_T1_fname) ;
        MRIwrite(mri_PD, out_PD_fname) ;
        printf("writing residuals to %s...\n", residual_name) ;
        if (residual_name) {
          MRI *mri_res, *mri_res_total = NULL ;
          for (i = 0 ; i < nvolumes ; i++) {

            mri_res = compute_residuals(mri_flash[i], mri_T1, mri_PD) ;
            sprintf(fname, "%s%d.mgh", residual_name, i) ;
#if 0
            MRIwrite(mri_res, fname) ;
#endif
            if (!mri_res_total) {
              mri_res_total = MRIcopy(mri_res, NULL) ;
            } else {
              MRIsadd(mri_res, mri_res_total, mri_res_total) ;
            }

            MRIfree(&mri_res) ;
          }
          MRIsscalarMul(mri_res_total, mri_res_total, 1.0/(float)nvolumes) ;
          MRIssqrt(mri_res_total, mri_res_total) ;
          sprintf(fname, "%s.mgh", residual_name) ;
          MRIwrite(mri_res_total, fname) ;
        }
      }

      nvox = 0 ;
      total_rms = 0 ;
      for (y = 0 ; y < height ; y++) {
#if 0
        if (y%32 == 0 && nvox > 0)
          printf("z = %d, y = %d, avg rms=%2.1f, T1=%2.0f, PD=%2.0f...\n",
                 z, y, total_rms/(double)nvox, last_T1, last_PD) ;
#endif
        for (x = 0 ; x < width ; x++) {
#if 0
          for (i = 0 ; i < nvolumes ; i++)
            if (MRISvox(mri_flash[i],x,y,z) > thresh)
              break ;
          if (i >= nvolumes)
#else
          if (no_valid_data(mri_flash, nvolumes, x, y, z, thresh))
#endif
          {
            ignored++ ;
            MRISvox(mri_T1, x, y, z) = MRISvox(mri_PD, x, y, z) = 0 ;
            /*            last_T1 = last_PD = 1000 ;*/
            continue ;
          }
#if 0
          sse = findInitialParameters(mri_flash, nvolumes, x, y, z,
                                      last_PD-1000, last_PD+1000,
                                      last_T1-1000, last_T1+1000,
                                      &last_PD, &last_T1, 10) ;
#endif
#if 0
          sse = findInitialParameters(mri_flash, nvolumes, x, y, z,
                                      last_PD-100, last_PD+100,
                                      last_T1-100, last_T1+100,
                                      &last_PD, &last_T1, 10) ;
          if (last_T1 <= MIN_T1 || last_PD <= 0) {
            ignored++ ;
            MRISvox(mri_T1, x, y, z) = MRISvox(mri_PD, x, y, z) = 0 ;
            /*            last_T1 = last_PD = 1000 ;*/
            continue ;
          }
#endif
          sse = estimateVoxelParameters(mri_flash, nvolumes, x, y, z,
                                        mri_T1, mri_PD, nsteps) ;
          nvox++ ;
          last_T1 = MRISvox(mri_T1, x, y, z) ;
          last_PD = MRISvox(mri_PD, x, y, z) ;
          total_rms += sqrt(sse/nvolumes) ;
          if (!finite(total_rms))
            DiagBreak() ;
        }
      }
      avg_rms = total_rms / nvox ;
      if (!finite(avg_rms))
        DiagBreak() ;
    }
  }


  printf("writing T1 esimates to %s...\n", out_T1_fname) ;
  printf("writing PD estimates to %s...\n", out_PD_fname) ;
  MRIwrite(mri_T1, out_T1_fname) ;
  MRIwrite(mri_PD, out_PD_fname) ;
  if (residual_name) {
    MRI *mri_res_total = NULL ;

    for (i = 0 ; i < nvolumes ; i++) {
      MRI *mri_res ;

      mri_res = compute_residuals(mri_flash[i], mri_T1, mri_PD) ;
#if 0
      sprintf(fname, "%s%d.mgh", residual_name, i) ;
      MRIwrite(mri_res, fname) ;
#endif
      if (!mri_res_total) {
        mri_res_total = MRIcopy(mri_res, NULL) ;
      } else {
        MRIsadd(mri_res, mri_res_total, mri_res_total) ;
      }
      MRIfree(&mri_res) ;
    }
    MRIsscalarMul(mri_res_total, mri_res_total, 1.0/(float)nvolumes) ;
    MRIssqrt(mri_res_total, mri_res_total) ;
    sprintf(fname, "%s.mgh", residual_name) ;
    MRIwrite(mri_res_total, fname) ;
  }
  MRIfree(&mri_T1) ;
  MRIfree(&mri_PD) ;
  msec = TimerStop(&start) ;
  seconds = nint((float)msec/1000.0f) ;
  minutes = seconds / 60 ;
  seconds = seconds % 60 ;
  printf("parameter estimation took %d minutes and %d seconds.\n",
         minutes, seconds) ;
  exit(0) ;
  return(0) ;
}
Ejemplo n.º 28
0
Float lnn_sentence_stats(sentence_type *s, const lnn_weights_type* wt,
			 size_t nhidden, size_t nfeatures,
			 Float score0[], Float score1[], 
			 const lnn_weights_type* dL_dwt,
			 Float *sum_g, Float *sum_p, Float *sum_w) 
{ 
  Float max_correct_score, max_score;
  int i, j, k;
  Float Z = 0, logZ, Ecorrect_score = 0;
  
  size_t best_i = lnn_sentence_scores(s, wt, nhidden, nfeatures,
				      score0, score1, 
				      &max_correct_score, &max_score);

  *sum_g += s->g;
  *sum_p += s->parse[best_i].p;
  *sum_w += s->parse[best_i].w;
  
  if (s->Px == 0)  /* skip statistics calculation if Px == 0 */
    return 0;

  assert(max_correct_score <= max_score);

  for (i = 0; i < s->nparses; ++i) {   /* compute Z and Zw */
    assert(score1[i] <= max_score);
    Z += exp(score1[i] - max_score);
    assert(finite(Z));
    if (s->parse[i].Pyx > 0) 
      Ecorrect_score += s->parse[i].Pyx * score1[i];
  }

  logZ = log(Z) + max_score;

  /* calculate expectations */

  for (i = 0; i < s->nparses; ++i) {
    Float cp = exp(score1[i] - logZ);  /* P_w(y|x) */
    assert(finite(cp));

    if (s->parse[i].Pyx > 0)  /* P_e(y|x)  */
      cp -= s->parse[i].Pyx;

    assert(cp >= -1.0);
    assert(cp <= 1.0);
    
    cp *= s->Px;   /* multiply in weight of sentence */

    /* calculate derivatives */

    for (j = 0; j < nhidden; ++j) {
      Float g = score0[i*nhidden+j];
      Float dg_dx = 1 - g*g;  /* for tanh activation function */
      Float backward = cp * wt->w1[j] * dg_dx;
      dL_dwt->w1[j] += cp * score0[i*nhidden+j];
      dL_dwt->b0[j] += backward;
      
      for (k = 0; k < s->parse[i].nf; ++k)  /* features with 1 count */
	dL_dwt->w0[j*nfeatures+s->parse[i].f[k]] += backward;
      
      for (k = 0; k < s->parse[i].nfc; ++k) /* features with arbitrary counts */
	dL_dwt->w0[j*nfeatures+s->parse[i].fc[k].f] 
	  += backward * s->parse[i].fc[k].c;
    }
  }
  return - s->Px * (Ecorrect_score - logZ);
}  /* lnn_sentence_stats() */
Ejemplo n.º 29
0
/************************************************************

  general_newton_raphson(): 

    -- performs Newton-Rapshon method on an arbitrary system.

    -- inspired in part by Num. Rec.'s routine newt();

    Arguements: 

       -- x[]   = set of independent variables to solve for;
       -- n     = number of independent variables and residuals;
       -- funcd = name of function that calculates residuals, etc.;

*****************************************************************/
static int general_newton_raphson( FTYPE x[], int n, 
				   void (*funcd) (FTYPE [], FTYPE [], FTYPE [], 
						  FTYPE [][NEWT_DIM], FTYPE *, 
						  FTYPE *, int) )
{
  FTYPE f, df, dx[NEWT_DIM], x_old[NEWT_DIM], resid[NEWT_DIM], 
    jac[NEWT_DIM][NEWT_DIM];
  FTYPE errx, x_orig[NEWT_DIM];
  int    n_iter, id, jd, i_extra, doing_extra;
  FTYPE dW,dvsq,vsq_old,vsq,W,W_old, rho,p,u;

  int   keep_iterating;


  // Initialize various parameters and variables:
  errx = 1. ; 
  df =  f = 1.;
  i_extra = doing_extra = 0;

  for( id = 0; id < n ; id++)  x_old[id] = x_orig[id] = x[id] ;

  vsq_old = vsq = W = W_old = 0.;

  n_iter = 0;


  /* Start the Newton-Raphson iterations : */
  keep_iterating = 1;
  while( keep_iterating ) { 

    (*funcd) (x, dx, resid, jac, &f, &df, n);  /* returns with new dx, f, df */


    /* Save old values before calculating the new: */
    errx = 0.;
    for( id = 0; id < n ; id++) {
      x_old[id] = x[id] ;
    }

    for( id = 0; id < n ; id++) {
      x[id] += dx[id]  ;
    }

    /****************************************/
    /* Make sure that the new x[] is physical : */
    /****************************************/
    // METHOD specific
    validate_x( x, x_old );


    /****************************************/
    /* Calculate the convergence criterion */
    /****************************************/

    /* For the new criterion, always look at error in "W" : */
    // METHOD specific
    W_old = W;
    W = W_of_vsq( x[0], &p, &rho, &u);
    errx  = (W==0.) ?  fabs(W-W_old) : fabs((W-W_old)/W);
    errx += (x[0]==0.) ?  fabs(x[0]-x_old[0]) : fabs((x[0]-x_old[0])/x[0]);


//    fprintf(stderr,"NR: %26.20e  %26.20e  %26.20e  %26.20e  %26.20e  \n", x_old[0], x[0], resid[0], jac[0][0], errx);
//    fflush(stderr);

    /*****************************************************************************/
    /* If we've reached the tolerance level, then just do a few extra iterations */
    /*   before stopping                                                         */
    /*****************************************************************************/
    
    if( (fabs(errx) <= NEWT_TOL) && (doing_extra == 0) && (EXTRA_NEWT_ITER > 0) ) {
      doing_extra = 1;
    }

    if( doing_extra == 1 ) i_extra++ ;

    // See if we've done the extra iterations, or have done too many iterations:
    if( ((fabs(errx) <= NEWT_TOL)&&(doing_extra == 0)) 
	|| (i_extra > EXTRA_NEWT_ITER) || (n_iter >= (MAX_NEWT_ITER-1)) ) {
      keep_iterating = 0;
    }

    n_iter++;

  }   // END of while(keep_iterating)


  /*  Check for bad untrapped divergences : */
  if( (finite(f)==0) || (finite(df)==0) ) {
    return(2);
  }

  // Return in different ways depending on whether a solution was found:
  if( fabs(errx) > MIN_NEWT_TOL){
#if(LTRACE)
    fprintf(stderr," totalcount = %d   0   %d  %26.20e \n",n_iter,i_extra,errx); fflush(stderr);                      
#endif
    return(1);
  }
  if( (fabs(errx) <= MIN_NEWT_TOL) && (fabs(errx) > NEWT_TOL) ){
    //fprintf(stderr," totalcount = %d   1   %d  %26.20e \n",n_iter,i_extra,errx); fflush(stderr);
    return(0);
  }
  if( fabs(errx) <= NEWT_TOL ){
    //fprintf(stderr," totalcount = %d   2   %d  %26.20e \n",n_iter,i_extra,errx); fflush(stderr); 
    return(0);
  }

  return(0);

}
Ejemplo n.º 30
0
int isfinite(double x)
{
	return finite(x) && !isnan(x);
}