void BaseShadowRenderImage::getTerrPolys( SimTerrain * terr)
{
   float rad = shadow.getShadowRadius();
	GridFile *terrFile = terr->getGridFile();
	const TMat3F & terrInv = terr->getInvTransform();

	// get the light direction in terrain space
	Point3F lightInTerr;
	m_mul(lastLight,(RMat3F&)terr->getInvTransform(),&lightInTerr);
	if (IsZero(lightInTerr.z,0.01f))
		return; // light parallel to x-y plane

	// center of shape in world coords
	Point3F shapeInWorld,preC;
   m_mul(shape->getShape().fCenter,shape->fRootDeltaTransform,&preC);
   m_mul(preC,transform,&shapeInWorld);

	// feet of shape in world coords
	Point3F feetInTerr;
   m_mul(transform.p,terrInv,&feetInTerr);

   // first task is to find plane on ground where light hits
   // this plane will be used to decide how big to make box
   // to grab terrain polys from
   Point3F n,p;
   float dot;
   bool gotIt = false;

   // first, are we standing on the terrain...if so, use this plane
   CollisionSurface cs;
   if (terrFile->getSurfaceInfo(feetInTerr,&cs))
   {
      if (IsZero(feetInTerr.z-cs.position.z,rad))
      {
         n = cs.normal;
         p = cs.position;
         dot = m_dot(n,lightInTerr);
         if (dot < -0.2f)
            gotIt = true;
      }
   }

   // now project in direction of light down from top of shape
   Point3F ta, a = shapeInWorld;
   a.z += rad;
   m_mul(a,terrInv,&ta);

   Point3F tb = lightInTerr;
   tb *= ShadowFeelerLength;
   tb += ta;
   GridCollision coll(terrFile,NULL);
   if (coll.collide(ta,tb) && terrFile->getSurfaceInfo(coll.surface.position,&cs))
   {
      float thisDot = m_dot(lightInTerr,coll.surface.normal);
      if (!gotIt || (thisDot > dot && thisDot < -0.2f))
      {
         n = coll.surface.normal;
         p = coll.surface.position;
         dot = thisDot;
         gotIt = true;
      }
   }
   
   if (!gotIt)
      return; // no terrain polys

	// shape center in terrain space
	Point3F shapeInTerr;
	m_mul(shapeInWorld,terrInv,&shapeInTerr);

   // we now have light, shape center, and a plane all in terrain space
   // build a box around projection of shape center onto plane
   Point3F shapeOnGround;
   float k = 1.0f / dot;
   float t = m_dot(n,p-shapeInTerr) * k;
   shapeOnGround  = lightInTerr;
   shapeOnGround *= t;
   shapeOnGround += shapeInTerr;

   // make the box
   Box2F shadowBox;
   shadowBox.fMin = shadowBox.fMax = shapeOnGround;
   float tx = -rad * n.x * k;
   float ty = -rad * n.y * k;
   float tz = -rad * n.z * k;
   shadowBox.fMin.x -= rad + tx*lightInTerr.x + 
                       fabs(ty*lightInTerr.x) + 
                       fabs(tz*lightInTerr.x);
   shadowBox.fMax.x += rad - tx*lightInTerr.x + 
                       fabs(ty*lightInTerr.x) + 
                       fabs(tz*lightInTerr.x);
   
   shadowBox.fMin.y -= rad + ty*lightInTerr.y + 
                       fabs(tx*lightInTerr.y) + 
                       fabs(tz*lightInTerr.y);
   shadowBox.fMax.y += rad - ty*lightInTerr.y + 
                       fabs(tx*lightInTerr.y) + 
                       fabs(tz*lightInTerr.y);
                       
   int maxPolys = min(shadow.projectionList.size() + BaseShadowRenderImage::maxTerrainPolys,
                      BaseShadowRenderImage::maxProjectionPolys);
   
	// now get polys from terrain to project shadow onto
	terrFile->getPolys(shadowBox,terr->getTransform(),shadow.projectionList,maxPolys);
}
Beispiel #2
0
void inv(zz_pE& d, mat_zz_pE& X, const mat_zz_pE& A)
{
   long n = A.NumRows();
   if (A.NumCols() != n)
      Error("inv: nonsquare matrix");

   if (n == 0) {
      set(d);
      X.SetDims(0, 0);
      return;
   }

   long i, j, k, pos;
   zz_pX t1, t2;
   zz_pX *x, *y;

   const zz_pXModulus& p = zz_pE::modulus();


   vec_zz_pX *M = newNTL_NEW_OP vec_zz_pX[n];

   for (i = 0; i < n; i++) {
      M[i].SetLength(2*n);
      for (j = 0; j < n; j++) {
         M[i][j].rep.SetMaxLength(2*deg(p)-1);
         M[i][j] = rep(A[i][j]);
         M[i][n+j].rep.SetMaxLength(2*deg(p)-1);
         clear(M[i][n+j]);
      }
      set(M[i][n+i]);
   }

   zz_pX det;
   set(det);

   for (k = 0; k < n; k++) {
      pos = -1;
      for (i = k; i < n; i++) {
         rem(t1, M[i][k], p);
         M[i][k] = t1;
         if (pos == -1 && !IsZero(t1)) {
            pos = i;
         }
      }

      if (pos != -1) {
         if (k != pos) {
            swap(M[pos], M[k]);
            negate(det, det);
         }

         MulMod(det, det, M[k][k], p);

         // make M[k, k] == -1 mod p, and make row k reduced

         InvMod(t1, M[k][k], p);
         negate(t1, t1);
         for (j = k+1; j < 2*n; j++) {
            rem(t2, M[k][j], p);
            MulMod(M[k][j], t2, t1, p);
         }

         for (i = k+1; i < n; i++) {
            // M[i] = M[i] + M[k]*M[i,k]

            t1 = M[i][k];   // this is already reduced

            x = M[i].elts() + (k+1);
            y = M[k].elts() + (k+1);

            for (j = k+1; j < 2*n; j++, x++, y++) {
               // *x = *x + (*y)*t1

               mul(t2, *y, t1);
               add(*x, *x, t2);
            }
         }
      }
      else {
         clear(d);
         goto done;
      }
   }

   X.SetDims(n, n);
   for (k = 0; k < n; k++) {
      for (i = n-1; i >= 0; i--) {
         clear(t1);
         for (j = i+1; j < n; j++) {
            mul(t2, rep(X[j][k]), M[i][j]);
            add(t1, t1, t2);
         }
         sub(t1, t1, M[i][n+k]);
         conv(X[i][k], t1);
      }
   }

   conv(d, det);

done:
   delete[] M;
}
Beispiel #3
0
void kernel(mat_zz_pE& X, const mat_zz_pE& A)
{
   long m = A.NumRows();
   long n = A.NumCols();

   mat_zz_pE M;
   long r;

   transpose(M, A);
   r = gauss(M);

   X.SetDims(m-r, m);

   long i, j, k, s;
   zz_pX t1, t2;

   zz_pE T3;

   vec_long D;
   D.SetLength(m);
   for (j = 0; j < m; j++) D[j] = -1;

   vec_zz_pE inverses;
   inverses.SetLength(m);

   j = -1;
   for (i = 0; i < r; i++) {
      do {
         j++;
      } while (IsZero(M[i][j]));

      D[j] = i;
      inv(inverses[j], M[i][j]); 
   }

   for (k = 0; k < m-r; k++) {
      vec_zz_pE& v = X[k];
      long pos = 0;
      for (j = m-1; j >= 0; j--) {
         if (D[j] == -1) {
            if (pos == k)
               set(v[j]);
            else
               clear(v[j]);
            pos++;
         }
         else {
            i = D[j];

            clear(t1);

            for (s = j+1; s < m; s++) {
               mul(t2, rep(v[s]), rep(M[i][s]));
               add(t1, t1, t2);
            }

            conv(T3, t1);
            mul(T3, T3, inverses[j]);
            negate(v[j], T3);
         }
      }
   }
}
Beispiel #4
0
	AUR_BOOL IsEqual( AUR_FLOAT32 p_Left, AUR_FLOAT32 p_Right )
	{
		return IsZero( p_Left - p_Right );
	}
Beispiel #5
0
 bool NotZero()     const { return !IsZero(); }
Beispiel #6
0
static
void NullSpace(long& r, vec_long& D, vec_ZZVec& M, long verbose)
{
   long k, l, n;
   long i, j;
   long pos;
   ZZ t1, t2;
   ZZ *x, *y;

   const ZZ& p = ZZ_p::modulus();

   n = M.length();

   D.SetLength(n);
   for (j = 0; j < n; j++) D[j] = -1;

   r = 0;

   l = 0;
   for (k = 0; k < n; k++) {

      if (verbose && k % 10 == 0) cerr << "+";

      pos = -1;
      for (i = l; i < n; i++) {
         rem(t1, M[i][k], p);
         M[i][k] = t1;
         if (pos == -1 && !IsZero(t1))
            pos = i;
      }

      if (pos != -1) {
         swap(M[pos], M[l]);

         // make M[l, k] == -1 mod p, and make row l reduced

         InvMod(t1, M[l][k], p);
         NegateMod(t1, t1, p);
         for (j = k+1; j < n; j++) {
            rem(t2, M[l][j], p);
            MulMod(M[l][j], t2, t1, p);
         }

         for (i = l+1; i < n; i++) {
            // M[i] = M[i] + M[l]*M[i,k]

            t1 = M[i][k];   // this is already reduced

            x = M[i].elts() + (k+1);
            y = M[l].elts() + (k+1);

            for (j = k+1; j < n; j++, x++, y++) {
               // *x = *x + (*y)*t1

               mul(t2, *y, t1);
               add(*x, *x, t2);
            }
         }

         D[k] = l;   // variable k is defined by row l
         l++;

      }
      else {
         r++;
      }
   }
}
Beispiel #7
0
/* item[n] = start + n * delta */
static 
Array MakeLinearList(Array start, Array end, int *n, Array delta)
{
    int i, j;
    Array a_start = NULL, a_end = NULL, a_delta = NULL;
    int delstart = 0, delend = 0, deldelta = 0;
    Array alist[3];
    Array output = NULL;
    int count = 1;
    int bytes;
    Type t;
    Category c;
    int rank;
    int shape[MAXSHAPE];
    int nitems;
    int i_start, i_end, i_delta;
    float f_start, f_end, f_delta, f_count;
    Pointer dp;
    int *ip;
    Object in[MAXCOMPINPUTS];  /* hardcoded in compute */
    Object out;
    String compstr = NULL;
    char cbuf[64];
    Error rc;

    /* do this or die in compute */
    for (i=0; i<MAXCOMPINPUTS; i++)
	in[i] = NULL;

    /* find common format of start, end, delta and check for 4 parms */
    i = 0;
    if (start)
	alist[i++] = start; 

    if (end)
	alist[i++] = end;

    if (delta)
	alist[i++] = delta;

    if (n) {
	count = *n;
	if (i == 3) {
	    DXWarning("too many inputs specified; ignoring delta");
	    i--;
	    delta = NULL;
	} 
    } 
    else if (i == 2)
	count = 2;

    
    if (i < 2) {
	DXSetError(ERROR_BAD_PARAMETER, 
		   "not enough inputs specified to generate a list");
	return NULL;
    }

    if (!DXQueryArrayCommonV(&t, &c, &rank, shape, i, alist)) {
	DXAddMessage("start, end and/or delta");
	return NULL;
    }

    /* shortcut the process here if the data is scalar integer or
     *  scalar float.  otherwise, if the data is vector or ubyte
     *  or whatever, fall through and use Compute so we can increment
     *  by irregular values.
     */
    if (t != TYPE_INT && t != TYPE_FLOAT)
	goto complicated;
    if (c != CATEGORY_REAL || rank != 0)
	goto complicated;


    /* compute missing value(s):
     * start = end - ((count - 1) * delta) 
     * end = start + ((count - 1) * delta) 
     * count = ((end - start) / delta) + 1 
     * delta = (end - start) / (count - 1) 
     */

    /* convert to the common format */
    if (start)
	a_start = DXArrayConvertV(start, t, c, rank, shape);
    if (end)
	a_end   = DXArrayConvertV(end,   t, c, rank, shape);
    if (delta)
	a_delta = DXArrayConvertV(delta, t, c, rank, shape);


    /* for integer, scalar lists */
    if (t == TYPE_INT) {
	if (!start) {
	    i_end = *(int *)DXGetArrayData(a_end);
	    i_delta = *(int *)DXGetArrayData(a_delta);
	    
	    i_start = i_end - ((count - 1) * i_delta);
	}

	if (!end) {
	    i_start = *(int *)DXGetArrayData(a_start);
	    i_delta = *(int *)DXGetArrayData(a_delta);
	    
	    i_end = i_start + ((count - 1) * i_delta);
	} 

	if (!delta) {
	    /* if count == 1, generate a zero of the right type.  otherwise
	     *  divide to figure out the right delta to make count-1 steps 
	     *  between start and end.  it's count-1 because if you want
	     *  N numbers between start and end, you have N-1 increments.
	     */
	    i_start = *(int *)DXGetArrayData(a_start);
	    i_end = *(int *)DXGetArrayData(a_end);
	    if (count == 1)
		i_delta = 0;
	    else
		i_delta = (i_end - i_start) / (count - 1);
	    
	    /* try to catch the case where delta ends up being 0 (like
	     * because the inputs are int and the count is larger than
	     * the difference between start and end).  allow it to be zero
	     * only if start == end;  i suppose if you ask for 10 things
	     * where start == end you should be able to get them.
	     */
	    if (i_delta == 0 && i_start != i_end) {
		DXSetError(ERROR_BAD_PARAMETER, 
		     "count too large to generate list between start and end");
		goto error;
	    }
	    
	}

	/* if all three arrays are there, count must be missing */
	if (i == 3) {
	    i_start = *(int *)DXGetArrayData(a_start);
	    i_end = *(int *)DXGetArrayData(a_end);
	    i_delta = *(int *)DXGetArrayData(a_delta);

	    if (i_delta == 0)
		count = 1;
	    else {
		if ((i_end >= i_start && i_delta > 0) ||
		    (i_end < i_start && i_delta < 0))
		    count = (int)(((double)i_end-i_start) / (double)i_delta) +1;
		else {
		    if (i_delta < 0)
			DXSetError(ERROR_BAD_PARAMETER,
			   "delta must be positive if start is less than end");
		    else
			DXSetError(ERROR_BAD_PARAMETER,
			   "delta must be negative if end is less than start");
		    goto error;
		}
	    }
	}

	output = (Array)DXNewRegularArray(TYPE_INT, 1, count, 
					 (Pointer)&i_start, (Pointer)&i_delta);
    }

    /* for float, scalar lists */
    if (t == TYPE_FLOAT) {
	if (!start) {
	    f_end = *(float *)DXGetArrayData(a_end);
	    f_delta = *(float *)DXGetArrayData(a_delta);
	    
	    f_start = f_end - ((count - 1.0) * f_delta);
	}

	if (!end) {
	    f_start = *(float *)DXGetArrayData(a_start);
	    f_delta = *(float *)DXGetArrayData(a_delta);
	    
	    f_end = f_start + ((count - 1.0) * f_delta);
	}

	if (!delta) {
	    /* if count == 1, generate a zero of the right type.  otherwise
	     *  divide to figure out the right delta to make count-1 steps 
	     *  between start and end.  it's count-1 because if you want
	     *  N numbers between start and end, you have N-1 increments.
	     */
	    f_start = *(float *)DXGetArrayData(a_start);
	    f_end = *(float *)DXGetArrayData(a_end);
	    if (count == 1)
		f_delta = 0.0;
	    else 
		f_delta = (f_end - f_start) / (count - 1.0);

	    /* try to catch the case where delta ends up being 0 (like
	     * because the inputs are int and the count is larger than
	     * the difference between start and end).  allow it to be zero
	     * only if start == end;  i suppose if you ask for 10 things
	     * where start == end you should be able to get them.
	     */
	    if (f_delta == 0.0 && f_start != f_end) {
		DXSetError(ERROR_BAD_PARAMETER, 
		   "count too large to generate list between start and end");
		goto error;
	    }
	}

	/* if all three arrays are there, count must be missing */
	if (i == 3) {
	    f_start = *(float *)DXGetArrayData(a_start);
	    f_end = *(float *)DXGetArrayData(a_end);
	    f_delta = *(float *)DXGetArrayData(a_delta);

	    if (f_delta == 0.0)
		count = 1;
	    else {
		if ((f_end >= f_start && f_delta > 0) ||
		    (f_end < f_start && f_delta < 0)) {
		    /* the intermediate float variable below is to minimize
		     * float round-off error.  if delta is 0.1 and you
		     * ask for a list between 0 and 1, it does the math in
		     * double, the delta used is actually 0.10000001, and 
		     * you get counts = 10.9999999 instead of 11.  when
		     * converted directly to int it becomes just 10 and your 
		     * list ends at 0.9 instead of 1.  
		     * math in base 2 has some problems.
		     */
		    f_count = ((f_end - f_start) / f_delta) +1;
		    count = (int)f_count;
		} else {
		    if (f_delta < 0)
			DXSetError(ERROR_BAD_PARAMETER,
			   "delta must be positive if start is less than end");
		    else
			DXSetError(ERROR_BAD_PARAMETER,
			   "delta must be negative if end is less than start");
		    goto error;
		}
	    }
	}

	output = (Array)DXNewRegularArray(TYPE_FLOAT, 1, count, 
					 (Pointer)&f_start, (Pointer)&f_delta);
    }
    
    DXDelete((Object)a_start);
    DXDelete((Object)a_end);
    DXDelete((Object)a_delta);
    
    /* return Array */
    return output;
    

    /* input is a vector, or a data type different from int or float.
     * use compute so this code doesn't have to be replicated for each
     * different shape and type.
     */

  complicated:
    nitems = 1;
    for (j=0; j<rank; j++)
	nitems *= shape[j];

    /* compute missing value(s):
     * start = end - ((count - 1) * delta) 
     * end = start + ((count - 1) * delta) 
     * count = ((end - start) / delta) + 1 
     * delta = (end - start) / (count - 1) 
     */

    if (!start) {
	compstr = DXNewString("$0 - (($1 - 1) * $2)");
	if (!compstr)
	    goto error;
	
	in[0] = (Object)compstr;
	in[1] = (Object)end;
	in[3] = (Object)delta;
	in[2] = (Object)DXNewArray(TYPE_INT, CATEGORY_REAL, 0);
	if (!in[2])
	    goto error;
	if (!DXAddArrayData((Array)in[2], 0, 1, (Pointer)&count))
	    goto error;

	/* i need to explain this - it's basically so if compute was 
         * going to try to cache this, it could add a reference and
         * then later when i call delete the object won't get deleted
         * out from underneath compute.  (i know compute doesn't cache
         * things, but a different module might.)
	 */
	DXReference((Object)compstr);
	DXReference(in[2]);

	rc = m_Compute(in, &out);

	DXDelete((Object)compstr);
	compstr = NULL;
	DXDelete(in[2]);
	in[2] = NULL;

	if (rc == ERROR)
	    goto error;

	start = (Array)out;
	delstart++;
    }

    if (!end) {
	compstr = DXNewString("$0 + (($1 - 1) * $2)");
	if (!compstr)
	    goto error;
	
	in[0] = (Object)compstr;
	in[1] = (Object)start;
	in[3] = (Object)delta;
	in[2] = (Object)DXNewArray(TYPE_INT, CATEGORY_REAL, 0);
	if (!in[2])
	    goto error;
	if (!DXAddArrayData((Array)in[2], 0, 1, (Pointer)&count))
	    goto error;

	DXReference((Object)compstr);
	DXReference(in[2]);

	rc = m_Compute(in, &out);

	DXDelete((Object)compstr);
	compstr = NULL;
	DXDelete(in[2]);
	in[2] = NULL;

	if (rc == ERROR)
	    goto error;

	end = (Array)out;
	delend++;
    }

    if (!delta) {
	/* if count == 1, generate a zero of the right type.  otherwise
         *  divide to figure out the right delta to make count-1 steps 
	 *  between start and end.  it's count-1 because if you want
         *  N numbers between start and end, you have N-1 increments.
	 */
	if (count == 1)
	    compstr = DXNewString("$1 - $1");
	else
	    compstr = DXNewString("($2 - $0) / ($1 - 1)");
	if (!compstr)
	    goto error;
	
	in[0] = (Object)compstr;
	in[1] = (Object)start;
	in[3] = (Object)end;
	in[2] = (Object)DXNewArray(TYPE_INT, CATEGORY_REAL, 0);
	if (!in[2])
	    goto error;
	if (!DXAddArrayData((Array)in[2], 0, 1, (Pointer)&count))
	    goto error;

	DXReference((Object)compstr);
	DXReference(in[2]);

	rc = m_Compute(in, &out);

	DXDelete((Object)compstr);
	compstr = NULL;
	DXDelete(in[2]);
	in[2] = NULL;

	if (rc == ERROR)
	    goto error;

	delta = (Array)out;
	deldelta++;

	/* try to catch the case where delta ends up being 0 (like
	 * because the inputs are int and the count is larger than
	 * the difference between start and end).  allow it to be zero
	 * only if start == end;  i suppose if you ask for 10 things
	 * where start == end you should be able to get them.
	 */
	if (IsZero(delta) && !IsEqual(start, end)) {
	    DXSetError(ERROR_BAD_PARAMETER, 
		    "count too large to generate list between start and end");
	    goto error;
	}

    }

    /* if all three arrays are there, count must be missing */
    if (i == 3) {
	char tbuf[512];
	int firsttime = 1;
	int lastcount = 0;

	/* this loop allows us to to handle vectors or matricies as
	 *  well as scalars.   it requires that the deltas compute to
         *  a consistent count.  like start=[0 2 4], end=[4 8 16],
	 *  would work if delta=[1 2 4] but not if delta was [1 2 2].
	 */
	for (j=0; j < nitems; j++) {
	    /* i think this code only works for vectors - i'm not sure
             * what it will do with rank=2 data.
	     */

	    /* this point of this next compute expression:
	     * if the delta is 0, don't divide by zero - the count is 1. 
	     * if the end is smaller than the start, the delta has to be
             *  negative.  if it's not, return -1.  you can't generate a
             *  negative count from the equations, so this is a safe signal.
	     */
	    sprintf(tbuf, 
		    "float($2.%d) == 0.0   ? "
		    "  1 : "
		    " (  (($1.%d >= $0.%d) && ($2.%d > 0) || "
		    "     ($1.%d <  $0.%d) && ($2.%d < 0))    ? "
		    "       int(float($1.%d - $0.%d) / float($2.%d)) + 1 : "
		    "       -1 ) ", 
		    j, j, j, j, j, j, j, j, j, j);
	    compstr = DXNewString(tbuf);
	    if (!compstr)
		goto error;
	    
	    in[0] = (Object)compstr;
	    in[1] = (Object)start;
	    in[2] = (Object)end;
	    in[3] = (Object)delta;
	    
	    DXReference((Object)compstr);

	    rc = m_Compute(in, &out);
	    
	    DXDelete((Object)compstr);
	    compstr = NULL;
	    
	    if (rc == ERROR)
		goto error;
	    
	    if (!DXExtractInteger(out, &count)) {
		DXSetError(ERROR_BAD_PARAMETER, 
			   "can't compute number of items");
		goto error;
	    }

	    DXDelete((Object)out);
	    if (count == 0)
		continue;

	    if (count < 0) {
		if (IsNegative(delta))
		    DXSetError(ERROR_BAD_PARAMETER,
			 "delta must be positive if start is less than end");
		else
		    DXSetError(ERROR_BAD_PARAMETER,
			 "delta must be negative if end is less than start");
		goto error;
	    }

	    if (firsttime) {
		lastcount = count;
		firsttime = 0;
	    } else {
		if (count != lastcount) {
		    DXSetError(ERROR_BAD_PARAMETER, 
			   "inconsistent number of items required by inputs");
		    goto error;
		}
	    }
	}    
    }

    /* now have 4 consistant values - once again make sure they are
     * converted into an identical format.
     */
    a_start = DXArrayConvertV(start, t, c, rank, shape);
    a_end   = DXArrayConvertV(end,   t, c, rank, shape);
    a_delta = DXArrayConvertV(delta, t, c, rank, shape);

    /* make empty array with n items */
    output = DXNewArrayV(t, c, rank, shape);
    if (!output)
	goto error;

    if (!DXAddArrayData(output, 0, count, NULL))
	goto error;

    dp = DXGetArrayData(output);
    if (!dp)
	goto error;

    /* foreach n */
    /*  call compute to add delta */
    /*  memcpy to right offset in array */
    /* end */

    bytes = DXGetItemSize(output);

    sprintf(cbuf, "%s($0 + ($1 * $2))", TypeName(t));
    compstr = DXNewString(cbuf);
    if (!compstr)
	goto error;
    
    in[0] = (Object)compstr;
    in[1] = (Object)a_start;
    in[3] = (Object)a_delta;

    in[2] = (Object)DXNewArray(TYPE_INT, CATEGORY_REAL, 0);
    if (!in[2])
	goto error;
    if (!DXAddArrayData((Array)in[2], 0, 1, NULL))
	goto error;
    ip = (int *)DXGetArrayData((Array)in[2]);
    
    DXReference((Object)compstr);
    DXReference(in[2]);

    for (i=0; i<count; i++) {

	*ip = i;

	rc = m_Compute(in, &out);
	if (rc == ERROR)
	    goto error;

	memcpy(INCVOID(dp, bytes*i), DXGetArrayData((Array)out), bytes);
	DXDelete((Object)out);
    }

    DXDelete((Object)compstr);
    DXDelete(in[2]);
    DXDelete((Object)a_start);
    DXDelete((Object)a_end);
    DXDelete((Object)a_delta);
    if (delstart)
	DXDelete((Object)start);
    if (delend)
	DXDelete((Object)end);
    if (deldelta)
	DXDelete((Object)delta);

    /* return Array */
    return output;
    
  error:
    DXDelete((Object)output);
    DXDelete((Object)compstr);
    DXDelete((Object)a_start);
    DXDelete((Object)a_end);
    DXDelete((Object)a_delta);
    if (delstart)
	DXDelete((Object)start);
    if (delend)
	DXDelete((Object)end);
    if (deldelta)
	DXDelete((Object)delta);

    return NULL;
}
void resultant(ZZ_p& rres, const ZZ_pX& u, const ZZ_pX& v)
{
   if (deg(u) <= NTL_ZZ_pX_GCD_CROSSOVER || deg(v) <= NTL_ZZ_pX_GCD_CROSSOVER) { 
      PlainResultant(rres, u, v);
      return;
   }

   ZZ_pX u1, v1;

   u1 = u;
   v1 = v;

   ZZ_p res, t;
   set(res);

   if (deg(u1) == deg(v1)) {
      rem(u1, u1, v1);
      swap(u1, v1);

      if (IsZero(v1)) {
         clear(rres);
         return;
      }

      power(t, LeadCoeff(u1), deg(u1) - deg(v1));
      mul(res, res, t);
      if (deg(u1) & 1)
         negate(res, res);
   }
   else if (deg(u1) < deg(v1)) {
      swap(u1, v1);
      if (deg(u1) & deg(v1) & 1)
         negate(res, res);
   }

   // deg(u1) > deg(v1) && v1 != 0

   vec_ZZ_p cvec;
   vec_long  dvec;

   cvec.SetMaxLength(deg(v1)+2);
   dvec.SetMaxLength(deg(v1)+2);

   append(cvec, LeadCoeff(u1));
   append(dvec, deg(u1));


   while (deg(u1) > NTL_ZZ_pX_GCD_CROSSOVER && !IsZero(v1)) { 
      ResHalfGCD(u1, v1, cvec, dvec);

      if (!IsZero(v1)) {
         append(cvec, LeadCoeff(v1));
         append(dvec, deg(v1));
         rem(u1, u1, v1);
         swap(u1, v1);
      }
   }

   if (IsZero(v1) && deg(u1) > 0) {
      clear(rres);
      return;
   }

   long i, l;
   l = dvec.length();

   if (deg(u1) == 0) {
      // we went all the way...

      for (i = 0; i <= l-3; i++) {
         power(t, cvec[i+1], dvec[i]-dvec[i+2]);
         mul(res, res, t);
         if (dvec[i] & dvec[i+1] & 1)
            negate(res, res);
      }

      power(t, cvec[l-1], dvec[l-2]);
      mul(res, res, t);
   }
   else {
      for (i = 0; i <= l-3; i++) {
         power(t, cvec[i+1], dvec[i]-dvec[i+2]);
         mul(res, res, t);
         if (dvec[i] & dvec[i+1] & 1)
            negate(res, res);
      }

      power(t, cvec[l-1], dvec[l-2]-deg(v1));
      mul(res, res, t);
      if (dvec[l-2] & dvec[l-1] & 1)
         negate(res, res);

      PlainResultant(t, u1, v1);
      mul(res, res, t);
   }

   rres = res;
}
void HalfGCD(ZZ_pXMatrix& M_out, const ZZ_pX& U, const ZZ_pX& V, long d_red)
{
   if (IsZero(V) || deg(V) <= deg(U) - d_red) {
      set(M_out(0,0));   clear(M_out(0,1));
      clear(M_out(1,0)); set(M_out(1,1));
 
      return;
   }


   long n = deg(U) - 2*d_red + 2;
   if (n < 0) n = 0;

   ZZ_pX U1, V1;

   RightShift(U1, U, n);
   RightShift(V1, V, n);

   if (d_red <= NTL_ZZ_pX_HalfGCD_CROSSOVER) {
      IterHalfGCD(M_out, U1, V1, d_red);
      return;
   }

   long d1 = (d_red + 1)/2;
   if (d1 < 1) d1 = 1;
   if (d1 >= d_red) d1 = d_red - 1;

   ZZ_pXMatrix M1;

   HalfGCD(M1, U1, V1, d1);
   mul(U1, V1, M1);

   long d2 = deg(V1) - deg(U) + n + d_red;

   if (IsZero(V1) || d2 <= 0) {
      M_out = M1;
      return;
   }


   ZZ_pX Q;
   ZZ_pXMatrix M2;

   DivRem(Q, U1, U1, V1);
   swap(U1, V1);

   HalfGCD(M2, U1, V1, d2);

   ZZ_pX t(INIT_SIZE, deg(M1(1,1))+deg(Q)+1);

   mul(t, Q, M1(1,0));
   sub(t, M1(0,0), t);
   swap(M1(0,0), M1(1,0));
   swap(M1(1,0), t);

   t.kill();

   t.SetMaxLength(deg(M1(1,1))+deg(Q)+1);

   mul(t, Q, M1(1,1));
   sub(t, M1(0,1), t);
   swap(M1(0,1), M1(1,1));
   swap(M1(1,1), t);

   t.kill();

   mul(M_out, M2, M1); 
}
Beispiel #10
0
void KarMul(ZZX& c, const ZZX& a, const ZZX& b)
{
   if (IsZero(a) || IsZero(b)) {
      clear(c);
      return;
   }

   if (&a == &b) {
      KarSqr(c, a);
      return;
   }

   vec_ZZ mem;

   const ZZ *ap, *bp;
   ZZ *cp;

   long sa = a.rep.length();
   long sb = b.rep.length();

   if (&a == &c) {
      mem = a.rep;
      ap = mem.elts();
   }
   else
      ap = a.rep.elts();

   if (&b == &c) {
      mem = b.rep;
      bp = mem.elts();
   }
   else
      bp = b.rep.elts();

   c.rep.SetLength(sa+sb-1);
   cp = c.rep.elts();

   long maxa, maxb, xover;

   maxa = MaxBits(a);
   maxb = MaxBits(b);
   xover = 2;

   if (sa < xover || sb < xover)
      PlainMul(cp, ap, sa, bp, sb);
   else {
      /* karatsuba */

      long n, hn, sp, depth;

      n = max(sa, sb);
      sp = 0;
      depth = 0;
      do {
         hn = (n+1) >> 1;
         sp += (hn << 2) - 1;
         n = hn;
         depth++;
      } while (n >= xover);

      ZZVec stk;
      stk.SetSize(sp,
         ((maxa + maxb + NumBits(min(sa, sb)) + 2*depth + 10)
          + NTL_ZZ_NBITS-1)/NTL_ZZ_NBITS);

      KarMul(cp, ap, sa, bp, sb, stk.elts());
   }

   c.normalize();
}
void BerlekampMassey(ZZ_pX& h, const vec_ZZ_p& a, long m)
{
   ZZ_pX Lambda, Sigma, Temp;
   long L;
   ZZ_p Delta, Delta1, t1;
   long shamt;

   // cerr << "*** " << m << "\n";

   Lambda.SetMaxLength(m+1);
   Sigma.SetMaxLength(m+1);
   Temp.SetMaxLength(m+1);

   L = 0;
   set(Lambda);
   clear(Sigma);
   set(Delta);
   shamt = 0;

   long i, r, dl;

   for (r = 1; r <= 2*m; r++) {
      // cerr << r << "--";
      clear(Delta1);
      dl = deg(Lambda);
      for (i = 0; i <= dl; i++) {
         mul(t1, Lambda.rep[i], a[r-i-1]);
         add(Delta1, Delta1, t1);
      }

      if (IsZero(Delta1)) {
         shamt++;
         // cerr << "case 1: " << deg(Lambda) << " " << deg(Sigma) << " " << shamt << "\n";
      }
      else if (2*L < r) {
         div(t1, Delta1, Delta);
         mul(Temp, Sigma, t1);
         Sigma = Lambda;
         ShiftSub(Lambda, Temp, shamt+1);
         shamt = 0;
         L = r-L;
         Delta = Delta1;
         // cerr << "case 2: " << deg(Lambda) << " " << deg(Sigma) << " " << shamt << "\n";
      }
      else {
         shamt++;
         div(t1, Delta1, Delta);
         mul(Temp, Sigma, t1);
         ShiftSub(Lambda, Temp, shamt);
         // cerr << "case 3: " << deg(Lambda) << " " << deg(Sigma) << " " << shamt << "\n";
      }
   }

   // cerr << "finished: " << L << " " << deg(Lambda) << "\n"; 

   dl = deg(Lambda);
   h.rep.SetLength(L + 1);

   for (i = 0; i < L - dl; i++)
      clear(h.rep[i]);

   for (i = L - dl; i <= L; i++)
      h.rep[i] = Lambda.rep[L - i];
}
Beispiel #12
0
long IsX(const ZZX& a)
{
   return deg(a) == 1 && IsOne(LeadCoeff(a)) && IsZero(ConstTerm(a));
}
Beispiel #13
0
// Create new local-bridge
BRIDGE *BrNewBridge(HUB *h, char *name, POLICY *p, bool local, bool monitor, bool tapmode, char *tapaddr, bool limit_broadcast, LOCALBRIDGE *parent_local_bridge)
{
	BRIDGE *b;
	POLICY *policy;
	THREAD *t;
	// Validate arguments
	if (h == NULL || name == NULL || parent_local_bridge == NULL)
	{
		return NULL;
	}

	if (p == NULL)
	{
		policy = ClonePolicy(GetDefaultPolicy());
	}
	else
	{
		policy = ClonePolicy(p);
	}

	b = ZeroMalloc(sizeof(BRIDGE));
	b->Cedar = h->Cedar;
	b->Hub = h;
	StrCpy(b->Name, sizeof(b->Name), name);
	b->Policy = policy;
	b->Local = local;
	b->Monitor = monitor;
	b->TapMode = tapmode;
	b->LimitBroadcast = limit_broadcast;
	b->ParentLocalBridge = parent_local_bridge;

	if (b->TapMode)
	{
		if (tapaddr != NULL && IsZero(tapaddr, 6) == false)
		{
			Copy(b->TapMacAddress, tapaddr, 6);
		}
		else
		{
			GenMacAddress(b->TapMacAddress);
		}
	}

	if (monitor)
	{
		// Enabling monitoring mode
		policy->MonitorPort = true;
	}

	if (b->LimitBroadcast == false)
	{
		// Disable broadcast limiter
		policy->NoBroadcastLimiter = true;
	}

	// Start thread
	t = NewThread(BrBridgeThread, b);
	WaitThreadInit(t);
	ReleaseThread(t);

	return b;
}
Beispiel #14
0
// Add a local-bridge
void AddLocalBridge(CEDAR *c, char *hubname, char *devicename, bool local, bool monitor, bool tapmode, char *tapaddr, bool limit_broadcast)
{
	UINT i;
	HUB *h = NULL;
	LOCALBRIDGE *br = NULL;
	// Validate arguments
	if (c == NULL || hubname == NULL || devicename == NULL)
	{
		return;
	}

	if (OS_IS_UNIX(GetOsInfo()->OsType) == false)
	{
		tapmode = false;
	}

	LockList(c->HubList);
	{
		LockList(c->LocalBridgeList);
		{
			bool exists = false;

			// Ensure that the same configuration local-bridge doesn't exist already 
			for (i = 0;i < LIST_NUM(c->LocalBridgeList);i++)
			{
				LOCALBRIDGE *br = LIST_DATA(c->LocalBridgeList, i);
				if (StrCmpi(br->DeviceName, devicename) == 0)
				{
					if (StrCmpi(br->HubName, hubname) == 0)
					{
						if (br->TapMode == tapmode)
						{
							exists = true;
						}
					}
				}
			}

			if (exists == false)
			{
				// Add configuration
				br = ZeroMalloc(sizeof(LOCALBRIDGE));
				StrCpy(br->HubName, sizeof(br->HubName), hubname);
				StrCpy(br->DeviceName, sizeof(br->DeviceName), devicename);
				br->Bridge = NULL;
				br->Local = local;
				br->TapMode = tapmode;
				br->LimitBroadcast = limit_broadcast;
				br->Monitor = monitor;
				if (br->TapMode)
				{
					if (tapaddr != NULL && IsZero(tapaddr, 6) == false)
					{
						Copy(br->TapMacAddress, tapaddr, 6);
					}
					else
					{
						GenMacAddress(br->TapMacAddress);
					}
				}

				Add(c->LocalBridgeList, br);

				// Find the hub
				for (i = 0;i < LIST_NUM(c->HubList);i++)
				{
					HUB *hub = LIST_DATA(c->HubList, i);
					if (StrCmpi(hub->Name, br->HubName) == 0)
					{
						h = hub;
						AddRef(h->ref);
						break;
					}
				}
			}
		}
		UnlockList(c->LocalBridgeList);
	}
	UnlockList(c->HubList);

	// Start the local-bridge immediately
	if (h != NULL && br != NULL && h->Type != HUB_TYPE_FARM_DYNAMIC)
	{
		Lock(h->lock_online);
		{
			if (h->Offline == false)
			{
				LockList(c->LocalBridgeList);
				{
					if (IsInList(c->LocalBridgeList, br))
					{
						if (br->Bridge == NULL)
						{
							br->Bridge = BrNewBridge(h, br->DeviceName, NULL, br->Local, br->Monitor, br->TapMode, br->TapMacAddress, br->LimitBroadcast, br);
						}
					}
				}
				UnlockList(c->LocalBridgeList);
			}
		}
		Unlock(h->lock_online);
	}

	ReleaseHub(h);
}
Beispiel #15
0
/**
 * Advances a fling by an interpolated amount based on the Android OverScroller.
 * This should be called whenever sampling the content transform for this
 * frame. Returns true if the fling animation should be advanced by one frame,
 * or false if there is no fling or the fling has ended.
 */
bool
AndroidFlingAnimation::DoSample(FrameMetrics& aFrameMetrics,
                                const TimeDuration& aDelta)
{
  bool shouldContinueFling = true;

  mOverScroller->ComputeScrollOffset(&shouldContinueFling);
  // OverScroller::GetCurrVelocity will sometimes return NaN. So need to externally
  // calculate current velocity and not rely on what the OverScroller calculates.
  // mOverScroller->GetCurrVelocity(&speed);
  int32_t currentX = 0;
  int32_t currentY = 0;
  mOverScroller->GetCurrX(&currentX);
  mOverScroller->GetCurrY(&currentY);
  ParentLayerPoint offset((float)currentX, (float)currentY);

  bool hitBoundX = CheckBounds(mApzc.mX, offset.x, mFlingDirection.x, &(offset.x));
  bool hitBoundY = CheckBounds(mApzc.mY, offset.y, mFlingDirection.y, &(offset.y));

  ParentLayerPoint velocity = mPreviousVelocity;

  // Sometimes the OverScroller fails to update the offset for a frame.
  // If the frame can still scroll we just use the velocity from the previous
  // frame. However, if the frame can no longer scroll in the direction
  // of the fling, then end the animation.
  if (offset != mPreviousOffset) {
    if (aDelta.ToMilliseconds() > 0) {
      velocity = (offset - mPreviousOffset) / (float)aDelta.ToMilliseconds();
      mPreviousVelocity = velocity;
    }
  } else if (hitBoundX || hitBoundY) {
    // We have reached the end of the scroll in one of the directions being scrolled and the offset has not
    // changed so end animation.
    shouldContinueFling = false;
  }

  float speed = velocity.Length();

  // gfxPrefs::APZFlingStoppedThreshold is only used in tests.
  if (!shouldContinueFling || (speed < gfxPrefs::APZFlingStoppedThreshold())) {
    if (shouldContinueFling) {
      // The OverScroller thinks it should continue but the speed is below
      // the stopping threshold so abort the animation.
      mOverScroller->AbortAnimation();
    }
    // This animation is going to end. If DeferHandleFlingOverscroll
    // has not been called and there is still some velocity left,
    // call it so that fling hand off may occur if applicable.
    if (!mSentBounceX && !mSentBounceY && (speed > 0.0f)) {
      DeferHandleFlingOverscroll(velocity);
    }
    return false;
  }

  mPreviousOffset = offset;

  mApzc.SetVelocityVector(velocity);
  aFrameMetrics.SetScrollOffset(offset / aFrameMetrics.GetZoom());

  // If we hit a bounds while flinging, send the velocity so that the bounce
  // animation can play.
  if (hitBoundX || hitBoundY) {
    ParentLayerPoint bounceVelocity = velocity;

    if (!mSentBounceX && hitBoundX && fabsf(offset.x - mStartOffset.x) > BOUNDS_EPSILON) {
      mSentBounceX = true;
    } else {
      bounceVelocity.x = 0.0f;
    }

    if (!mSentBounceY && hitBoundY && fabsf(offset.y - mStartOffset.y) > BOUNDS_EPSILON) {
      mSentBounceY = true;
    } else {
      bounceVelocity.y = 0.0f;
    }
    if (!IsZero(bounceVelocity)) {
      DeferHandleFlingOverscroll(bounceVelocity);
    }
  }

  return true;
}
void XHalfGCD(ZZ_pXMatrix& M_out, ZZ_pX& U, ZZ_pX& V, long d_red)
{
   if (IsZero(V) || deg(V) <= deg(U) - d_red) {
      set(M_out(0,0));   clear(M_out(0,1));
      clear(M_out(1,0)); set(M_out(1,1));
 
      return;
   }

   long du = deg(U);

   if (d_red <= NTL_ZZ_pX_HalfGCD_CROSSOVER) {
      IterHalfGCD(M_out, U, V, d_red);
      return;
   }

   long d1 = (d_red + 1)/2;
   if (d1 < 1) d1 = 1;
   if (d1 >= d_red) d1 = d_red - 1;

   ZZ_pXMatrix M1;

   HalfGCD(M1, U, V, d1);
   mul(U, V, M1);

   long d2 = deg(V) - du + d_red;

   if (IsZero(V) || d2 <= 0) {
      M_out = M1;
      return;
   }


   ZZ_pX Q;
   ZZ_pXMatrix M2;

   DivRem(Q, U, U, V);
   swap(U, V);

   XHalfGCD(M2, U, V, d2);

   ZZ_pX t(INIT_SIZE, deg(M1(1,1))+deg(Q)+1);

   mul(t, Q, M1(1,0));
   sub(t, M1(0,0), t);
   swap(M1(0,0), M1(1,0));
   swap(M1(1,0), t);

   t.kill();

   t.SetMaxLength(deg(M1(1,1))+deg(Q)+1);

   mul(t, Q, M1(1,1));
   sub(t, M1(0,1), t);
   swap(M1(0,1), M1(1,1));
   swap(M1(1,1), t);

   t.kill();

   mul(M_out, M2, M1); 
}
Beispiel #17
0
/* Both ellipses are assumed to have non-zero radii */
int Int2Elip(Point *IntPts,Ellipse *E1,Ellipse *E2)
   {
   TMat ElpCirMat1,ElpCirMat2,InvMat,TempMat;
   Conic Conic1,Conic2,Conic3,TempConic;
   double Roots[3],qRoots[2];
   static Circle TestCir = {{0.0,0.0},1.0};
   Line TestLine[2];
   Point TestPoint;
   double PolyCoef[4];		/* coefficients of the polynomial */
   double D;			/* discriminant: B^2 - AC */
   double Phi;			/* ellipse rotation */
   double m,n;			/* ellipse translation */
   double Scl;			/* scaling factor */
   int NumRoots,NumLines;
   int CircleInts;		/* intersections between line and circle */
   int IntCount = 0;		/* number of intersections found */
   int i,j,k;

   /* compute the transformations which turn E1 and E2 into circles */
   Elp2Cir(E1,&ElpCirMat1);
   Elp2Cir(E2,&ElpCirMat2);

   /* compute the inverse transformation of ElpCirMat1 */
   InvElp2Cir(E1,&InvMat);

   /* Compute the characteristic matrices */
   GenEllipseCoefs(E1,&Conic1);
   GenEllipseCoefs(E2,&Conic2);

   /* Find x such that Det(Conic1 + x Conic2) = 0 */
   PolyCoef[0] = -Conic1.C*Conic1.D*Conic1.D + 2.0*Conic1.B*Conic1.D*Conic1.E -
      Conic1.A*Conic1.E*Conic1.E - Conic1.B*Conic1.B*Conic1.F +
      Conic1.A*Conic1.C*Conic1.F;
   PolyCoef[1] = -(Conic2.C*Conic1.D*Conic1.D) -
      2.0*Conic1.C*Conic1.D*Conic2.D + 2.0*Conic2.B*Conic1.D*Conic1.E +
      2.0*Conic1.B*Conic2.D*Conic1.E - Conic2.A*Conic1.E*Conic1.E +
      2.0*Conic1.B*Conic1.D*Conic2.E - 2.0*Conic1.A*Conic1.E*Conic2.E -
      2.0*Conic1.B*Conic2.B*Conic1.F + Conic2.A*Conic1.C*Conic1.F +
      Conic1.A*Conic2.C*Conic1.F - Conic1.B*Conic1.B*Conic2.F +
      Conic1.A*Conic1.C*Conic2.F;
   PolyCoef[2] = -2.0*Conic2.C*Conic1.D*Conic2.D - Conic1.C*Conic2.D*Conic2.D +
      2.0*Conic2.B*Conic2.D*Conic1.E + 2.0*Conic2.B*Conic1.D*Conic2.E +
      2.0*Conic1.B*Conic2.D*Conic2.E - 2.0*Conic2.A*Conic1.E*Conic2.E -
      Conic1.A*Conic2.E*Conic2.E - Conic2.B*Conic2.B*Conic1.F +
      Conic2.A*Conic2.C*Conic1.F - 2.0*Conic1.B*Conic2.B*Conic2.F +
      Conic2.A*Conic1.C*Conic2.F + Conic1.A*Conic2.C*Conic2.F;
   PolyCoef[3] = -Conic2.C*Conic2.D*Conic2.D + 2.0*Conic2.B*Conic2.D*Conic2.E -
      Conic2.A*Conic2.E*Conic2.E - Conic2.B*Conic2.B*Conic2.F +
      Conic2.A*Conic2.C*Conic2.F;
   NumRoots = SolveCubic(PolyCoef,Roots);

   if (NumRoots == 0)
      return 0;

   /* we try all the roots, even though it's redundant, so that we
      avoid some pathological situations */
   for (i=0;i<NumRoots;i++)
      {
      NumLines = 0;

      /* Conic3 = Conic1 + mu Conic2 */
      Conic3.A = Conic1.A + Roots[i]*Conic2.A;
      Conic3.B = Conic1.B + Roots[i]*Conic2.B;
      Conic3.C = Conic1.C + Roots[i]*Conic2.C;
      Conic3.D = Conic1.D + Roots[i]*Conic2.D;
      Conic3.E = Conic1.E + Roots[i]*Conic2.E;
      Conic3.F = Conic1.F + Roots[i]*Conic2.F;

      D = Conic3.B*Conic3.B - Conic3.A*Conic3.C;
      if (IsZero(Conic3.A) && IsZero(Conic3.B) && IsZero(Conic3.C))
	 {
	 /* Case 1 - Single line */
	 NumLines = 1;
	 /* compute endpoints of the line, avoiding division by zero */
	 if (fabs(Conic3.D) > fabs(Conic3.E))
	    {
	    TestLine[0].P1.Y = 0.0;
	    TestLine[0].P1.X = -Conic3.F/(Conic3.D + Conic3.D);
	    TestLine[0].P2.Y = 1.0;
	    TestLine[0].P2.X = -(Conic3.E + Conic3.E + Conic3.F)/
	       (Conic3.D + Conic3.D);
	    }
	 else
	    {
	    TestLine[0].P1.X = 0.0;
	    TestLine[0].P1.Y = -Conic3.F/(Conic3.E + Conic3.E);
	    TestLine[0].P2.X = 1.0;
	    TestLine[0].P2.Y = -(Conic3.D + Conic3.D + Conic3.F)/
	       (Conic3.E + Conic3.E);
	    }
	 }
      else
	 {
	 /* use the espresion for Phi that takes atan of the
	    smallest argument */
	 Phi = (fabs(Conic3.B + Conic3.B) < fabs(Conic3.A-Conic3.C)?
	    atan((Conic3.B + Conic3.B)/(Conic3.A - Conic3.C)):
	    M_PI_2 - atan((Conic3.A - Conic3.C)/(Conic3.B + Conic3.B)))/2.0;
	 if (IsZero(D))
	    {
	    /* Case 2 - Parallel lines */
	    TempConic = Conic3;
	    TempMat = IdentMat;
	    RotateMat(&TempMat,-Phi);
	    TransformConic(&TempConic,&TempMat);
	    if (IsZero(TempConic.C))   /* vertical */
	       {
	       PolyCoef[0] = TempConic.F;
	       PolyCoef[1] = 2*TempConic.D;
	       PolyCoef[2] = TempConic.A;
	       if ((NumLines=SolveQuadic(PolyCoef,qRoots))!=0)
		  {
		  TestLine[0].P1.X = qRoots[0];
		  TestLine[0].P1.Y = -1.0;
		  TestLine[0].P2.X = qRoots[0];
		  TestLine[0].P2.Y = 1.0;
		  if (NumLines==2)
		     {
		     TestLine[1].P1.X = qRoots[1];
		     TestLine[1].P1.Y = -1.0;
		     TestLine[1].P2.X = qRoots[1];
		     TestLine[1].P2.Y = 1.0;
		     }
		  }
	       }
	    else		    /* horizontal */
	       {
	       PolyCoef[0] = TempConic.F;
	       PolyCoef[1] = 2*TempConic.E;
	       PolyCoef[2] = TempConic.C;
	       if ((NumLines=SolveQuadic(PolyCoef,qRoots))!=0)
		  {
		  TestLine[0].P1.X = -1.0;
		  TestLine[0].P1.Y = qRoots[0];
		  TestLine[0].P2.X = 1.0;
		  TestLine[0].P2.Y = qRoots[0];
		  if (NumLines==2)
		     {
		     TestLine[1].P1.X = -1.0;
		     TestLine[1].P1.Y = qRoots[1];
		     TestLine[1].P2.X = 1.0;
		     TestLine[1].P2.Y = qRoots[1];
		     }
		  }
	       }
	    TempMat = IdentMat;
	    RotateMat(&TempMat,Phi);
	    TransformPoint(&TestLine[0].P1,&TempMat);
	    TransformPoint(&TestLine[0].P2,&TempMat);
	    if (NumLines==2)
	       {
	       TransformPoint(&TestLine[1].P1,&TempMat);
	       TransformPoint(&TestLine[1].P2,&TempMat);
	       }
	    }
	 else
	    {
	    /* Case 3 - Crossing lines */
	    NumLines = 2;

	    /* translate the system so that the intersection of the lines
	       is at the origin */
	    TempConic = Conic3;
	    m = (Conic3.C*Conic3.D - Conic3.B*Conic3.E)/D;
	    n = (Conic3.A*Conic3.E - Conic3.B*Conic3.D)/D;
	    TempMat = IdentMat;
	    TranslateMat(&TempMat,-m,-n);
	    RotateMat(&TempMat,-Phi);
	    TransformConic(&TempConic,&TempMat);

	    /* Compute the line endpoints */
	    TestLine[0].P1.X = sqrt(fabs(1.0/TempConic.A));
	    TestLine[0].P1.Y = sqrt(fabs(1.0/TempConic.C));
	    Scl = max(TestLine[0].P1.X,TestLine[0].P1.Y);  /* adjust range */
	    TestLine[0].P1.X /= Scl;
	    TestLine[0].P1.Y /= Scl;
	    TestLine[0].P2.X = - TestLine[0].P1.X;
	    TestLine[0].P2.Y = - TestLine[0].P1.Y;
	    TestLine[1].P1.X = TestLine[0].P1.X;
	    TestLine[1].P1.Y = - TestLine[0].P1.Y;
	    TestLine[1].P2.X = - TestLine[1].P1.X;
	    TestLine[1].P2.Y = - TestLine[1].P1.Y;

	    /* translate the lines back */
	    TempMat = IdentMat;
	    RotateMat(&TempMat,Phi);
	    TranslateMat(&TempMat,m,n);
	    TransformPoint(&TestLine[0].P1,&TempMat);
	    TransformPoint(&TestLine[0].P2,&TempMat);
	    TransformPoint(&TestLine[1].P1,&TempMat);
	    TransformPoint(&TestLine[1].P2,&TempMat);
	    }
	 }

      /* find the ellipse line intersections */
      for (j = 0;j < NumLines;j++)
	 {
	 /* transform the line endpts into the circle space of the ellipse */
	 TransformPoint(&TestLine[j].P1,&ElpCirMat1);
	 TransformPoint(&TestLine[j].P2,&ElpCirMat1);

	 /* compute the number of intersections of the transformed line
	    and test circle */
	 CircleInts = IntCirLine(&IntPts[IntCount],&TestCir,&TestLine[j]);
	 if (CircleInts>0)
	    {
	    /* transform the intersection points back into ellipse space */
	    for (k = 0;k < CircleInts;k++)
	       TransformPoint(&IntPts[IntCount+k],&InvMat);
	    /* update the number of intersections found */
	    IntCount += CircleInts;
	    }
	 }
      }
   /* validate the points */
   j = IntCount;
   IntCount = 0;
   for (i = 0;i < j;i++)
      {
      TestPoint = IntPts[i];
      TransformPoint(&TestPoint,&ElpCirMat2);
      if (TestPoint.X < 2.0 && TestPoint.Y < 2.0 &&
	 IsZero(1.0 - sqrt(TestPoint.X*TestPoint.X +
	 TestPoint.Y*TestPoint.Y)))
	 IntPts[IntCount++]=IntPts[i];
      }
   return IntCount;
   }
void interpolate(ZZ_pX& f, const vec_ZZ_p& a, const vec_ZZ_p& b)
{
   long m = a.length();
   if (b.length() != m) LogicError("interpolate: vector length mismatch");

   if (m == 0) {
      clear(f);
      return;
   }

   vec_ZZ_p prod;
   prod = a;

   ZZ_p t1, t2;

   long k, i;

   vec_ZZ_p res;
   res.SetLength(m);

   for (k = 0; k < m; k++) {

      const ZZ_p& aa = a[k];

      set(t1);
      for (i = k-1; i >= 0; i--) {
         mul(t1, t1, aa);
         add(t1, t1, prod[i]);
      }

      clear(t2);
      for (i = k-1; i >= 0; i--) {
         mul(t2, t2, aa);
         add(t2, t2, res[i]);
      }


      inv(t1, t1);
      sub(t2, b[k], t2);
      mul(t1, t1, t2);

      for (i = 0; i < k; i++) {
         mul(t2, prod[i], t1);
         add(res[i], res[i], t2);
      }

      res[k] = t1;

      if (k < m-1) {
         if (k == 0)
            negate(prod[0], prod[0]);
         else {
            negate(t1, a[k]);
            add(prod[k], t1, prod[k-1]);
            for (i = k-1; i >= 1; i--) {
               mul(t2, prod[i], t1);
               add(prod[i], t2, prod[i-1]);
            }
            mul(prod[0], prod[0], t1);
         }
      }
   }

   while (m > 0 && IsZero(res[m-1])) m--; 
   res.SetLength(m);
   f.rep = res;
}
Beispiel #19
0
void inv(ZZ& d_out, mat_ZZ& x_out, const mat_ZZ& A, long deterministic)
{
   long n = A.NumRows();

   if (A.NumCols() != n)
      Error("solve: nonsquare matrix");

   if (n == 0) {
      set(d_out);
      x_out.SetDims(0, 0);
      return;
   }

   zz_pBak zbak;
   zbak.save();

   ZZ_pBak Zbak;
   Zbak.save();

   mat_ZZ x(INIT_SIZE, n, n);
   ZZ d, d1;

   ZZ d_prod, x_prod;
   set(d_prod);
   set(x_prod);

   long d_instable = 1;
   long x_instable = 1;

   long gp_cnt = 0;

   long check = 0;


   mat_ZZ y;

   long i;
   long bound = 2+DetBound(A);

   for (i = 0; ; i++) {
      if ((check || IsZero(d)) && !d_instable) {
         if (NumBits(d_prod) > bound) {
            break;
         }
         else if (!deterministic &&
                  bound > 1000 && NumBits(d_prod) < 0.25*bound) {

            ZZ P;

            long plen = 90 + NumBits(max(bound, NumBits(d)));
            GenPrime(P, plen, 90 + 2*NumBits(gp_cnt++));

            ZZ_p::init(P);

            mat_ZZ_p AA;
            conv(AA, A);

            ZZ_p dd;
            determinant(dd, AA);

            if (CRT(d, d_prod, rep(dd), P))
               d_instable = 1;
            else
               break;
         }
      }


      zz_p::FFTInit(i);
      long p = zz_p::modulus();

      mat_zz_p AA;
      conv(AA, A);

      if (!check) {
         mat_zz_p xx;

         zz_p dd;

         inv(dd, xx, AA);

         d_instable = CRT(d, d_prod, rep(dd), p);
         if (!IsZero(dd)) {
            mul(xx, xx, dd);
            x_instable = CRT(x, x_prod, xx);
         }
         else
            x_instable = 1;

         if (!d_instable && !x_instable) {
            mul(y, x, A);
            if (IsDiag(y, n, d)) {
               d1 = d;
               check = 1;
            }
         }
      }
      else {
         zz_p dd;
         determinant(dd, AA);
         d_instable = CRT(d, d_prod, rep(dd), p);
      }
   }

   if (check && d1 != d) {
      mul(x, x, d);
      ExactDiv(x, d1);
   }

   d_out = d;
   if (check) x_out = x;

   zbak.restore();
   Zbak.restore();
}
Beispiel #20
0
void Q_SetKer(QMatrix *Q, Vector *RightKer, Vector *LeftKer)
/* defines the null space in the case of a singular matrix */
{
    double Sum, Mean, Cmp, Norm;
    size_t Dim, Ind;
    Real *KerCmp;

    V_Lock(RightKer);
    V_Lock(LeftKer);

    if (LASResult() == LASOK) {
	if (Q->Dim == RightKer->Dim && (Q->Symmetry || Q->Dim == LeftKer->Dim)) {
  	    Dim = Q->Dim;

	    /* release array for old null space components when it exists */
	    if (Q->RightKerCmp != NULL) {
	        free(Q->RightKerCmp);
	        Q->RightKerCmp = NULL;
	    }
	    if (Q->LeftKerCmp != NULL) {
	        free(Q->LeftKerCmp);
	        Q->LeftKerCmp = NULL;
	    }
	    Q->UnitRightKer = False;
	    Q->UnitLeftKer = False;

	    /* right null space */
            KerCmp = RightKer->Cmp;
	    /* test whether the matrix Q has a unit right null space */
	    Sum = 0.0;
	    for(Ind = 1; Ind <= Dim; Ind++)
	        Sum += KerCmp[Ind];
	    Mean = Sum / (double)Dim;
	    Q->UnitRightKer = True;
	    if (!IsZero(Mean)) {
	        for(Ind = 1; Ind <= Dim; Ind++)
                    if (!IsOne(KerCmp[Ind] / Mean))
		        Q->UnitRightKer = False;
            } else {
	        Q->UnitRightKer = False;
	    }
	    if (!Q->UnitRightKer) {
	        Sum = 0.0;
	        for(Ind = 1; Ind <= Dim; Ind++) {
	            Cmp = KerCmp[Ind];
	            Sum += Cmp * Cmp;
	        }
		Norm = sqrt(Sum);
		if (!IsZero(Norm)) {
                    Q->RightKerCmp = (Real *)malloc((Dim + 1) * sizeof(Real));
		    if (Q->RightKerCmp != NULL) {
		        for(Ind = 1; Ind <= Dim; Ind++)
	                    Q->RightKerCmp[Ind] = KerCmp[Ind] / Norm;
		    } else {
	                LASError(LASMemAllocErr, "Q_SetKer", Q->Name, RightKer->Name,
		            LeftKer->Name);
		    }
		}
	    }

	    if (!Q->Symmetry) {
	        /* left null space */
                KerCmp = LeftKer->Cmp;
	        /* test whether the matrix Q has a unit left null space */
	        Sum = 0.0;
	        for(Ind = 1; Ind <= Dim; Ind++)
	            Sum += KerCmp[Ind];
	        Mean = Sum / (double)Dim;
	        Q->UnitLeftKer = True;
	        if (!IsZero(Mean)) {
	            for(Ind = 1; Ind <= Dim; Ind++)
                        if (!IsOne(KerCmp[Ind] / Mean))
		            Q->UnitLeftKer = False;
                } else {
	            Q->UnitLeftKer = False;
	        }
	        if (!Q->UnitLeftKer) {
	            Sum = 0.0;
	            for(Ind = 1; Ind <= Dim; Ind++) {
	                Cmp = KerCmp[Ind];
	                Sum += Cmp * Cmp;
	            }
		    Norm = sqrt(Sum);
		    if (!IsZero(Norm)) {
                        Q->LeftKerCmp = (Real *)malloc((Dim + 1) * sizeof(Real));
		        if (Q->LeftKerCmp != NULL) {
		            for(Ind = 1; Ind <= Dim; Ind++)
	                        Q->LeftKerCmp[Ind] = KerCmp[Ind] / Norm;
		        } else {
	                    LASError(LASMemAllocErr, "Q_SetKer", Q->Name,
				RightKer->Name, LeftKer->Name);
		        }
	    	    }
	        }
	    } else {
	    }
	} else {
	    LASError(LASDimErr, "Q_SetKer", Q->Name, RightKer->Name, LeftKer->Name);
	}
    }

    V_Unlock(RightKer);
    V_Unlock(LeftKer);
}
Beispiel #21
0
NTL_START_IMPL


void CharPolyMod(ZZX& gg, const ZZX& a, const ZZX& f, long deterministic)
{
   if (!IsOne(LeadCoeff(f)) || deg(f) < 1 || deg(a) >= deg(f))
      Error("CharPolyMod: bad args");


   if (IsZero(a)) {
      clear(gg);
      SetCoeff(gg, deg(f));
      return;
   }

   long bound = 2 + CharPolyBound(a, f);

   long gp_cnt = 0;

   zz_pBak bak;
   bak.save();

   ZZ_pBak bak1;
   bak1.save();

   ZZX g;
   ZZ prod;

   clear(g);
   set(prod);

   long i;

   long instable = 1;

   for (i = 0; ; i++) {
      if (NumBits(prod) > bound)
         break;

      if (!deterministic &&
          !instable && bound > 1000 && NumBits(prod) < 0.25*bound) {
         long plen = 90 + NumBits(max(bound, MaxBits(g)));

         ZZ P;

         GenPrime(P, plen, 90 + 2*NumBits(gp_cnt++));

         ZZ_p::init(P);
         ZZ_pX G, A, F;
         conv(A, a);
         conv(F, f);
         CharPolyMod(G, A, F);

         if (CRT(g, prod, G))
            instable = 1;
         else
            break;
      }

      zz_p::FFTInit(i);

      zz_pX G, A, F;
      conv(A, a);
      conv(F, f);
      CharPolyMod(G, A, F);
      instable = CRT(g, prod, G);
   }

   gg = g;

   bak.restore();
   bak1.restore();
}
Beispiel #22
0
bool Vector::operator == (const Vector& v) const
{
	if(IsZero(x - v.x) && IsZero(y - v.y) && IsZero(z - v.z)) return(true);
	return(false);
}
Beispiel #23
0
	LD_BOOL IsEqual( LD_FLOAT32 p_Left, LD_FLOAT32 p_Right )
	{
		return ( IsZero( p_Left - p_Right ) );
	}
Beispiel #24
0
float Ray::GetDistanceFrom(Ray& r)
{
	float t = (d | r.d);
	if(IsZero(t)) return(-BIGNUMBER); // plane is paralell to the ray, return -infinite
	return(((r.p - p) | r.d) / t);
}
Beispiel #25
0
void determinant(zz_pE& d, const mat_zz_pE& M_in)
{
   long k, n;
   long i, j;
   long pos;
   zz_pX t1, t2;
   zz_pX *x, *y;

   const zz_pXModulus& p = zz_pE::modulus();

   n = M_in.NumRows();

   if (M_in.NumCols() != n)
      Error("determinant: nonsquare matrix");

   if (n == 0) {
      set(d);
      return;
   }

   vec_zz_pX *M = newNTL_NEW_OP vec_zz_pX[n];

   for (i = 0; i < n; i++) {
      M[i].SetLength(n);
      for (j = 0; j < n; j++) {
         M[i][j].rep.SetMaxLength(2*deg(p)-1);
         M[i][j] = rep(M_in[i][j]);
      }
   }

   zz_pX det;
   set(det);

   for (k = 0; k < n; k++) {
      pos = -1;
      for (i = k; i < n; i++) {
         rem(t1, M[i][k], p);
         M[i][k] = t1;
         if (pos == -1 && !IsZero(t1))
            pos = i;
      }

      if (pos != -1) {
         if (k != pos) {
            swap(M[pos], M[k]);
            negate(det, det);
         }

         MulMod(det, det, M[k][k], p);

         // make M[k, k] == -1 mod p, and make row k reduced

         InvMod(t1, M[k][k], p);
         negate(t1, t1);
         for (j = k+1; j < n; j++) {
            rem(t2, M[k][j], p);
            MulMod(M[k][j], t2, t1, p);
         }

         for (i = k+1; i < n; i++) {
            // M[i] = M[i] + M[k]*M[i,k]

            t1 = M[i][k];   // this is already reduced

            x = M[i].elts() + (k+1);
            y = M[k].elts() + (k+1);

            for (j = k+1; j < n; j++, x++, y++) {
               // *x = *x + (*y)*t1

               mul(t2, *y, t1);
               add(*x, *x, t2);
            }
         }
      }
      else {
         clear(d);
         goto done;
      }
   }

   conv(d, det);

done:
   delete[] M;
}
Beispiel #26
0
void Slice::ConnectSegmentNeighbors()
{
	unsigned int s;
    unsigned int potential;
    unsigned int s2;
	double potentialangle;
	double potentialDist;
	double minDist = 10000.0;

	Segment* thisSeg = NULL;
	Segment* thatSeg = NULL;
    QVector2D* thisPoint = NULL;

    QVector2D* thatPoint = NULL;

    std::vector<Segment*> sameXStripSegs;
    std::vector<Segment*> potentialLeadSegs;

    Segment* finalLeadSeg = NULL;

	for(s = 0; s < segmentList.size(); s++)//compare from every segment
	{
		thisSeg = segmentList[s];
		thisPoint = &thisSeg->p2;//compare from the 2nd point on "this" segment

		if(thisSeg->leadingSeg)//no need to add a connection if there already is one!
			continue;
		
		potentialLeadSegs.clear();//clear out the potentials list
		

        GetSegmentsAroundX(sameXStripSegs, thisPoint->x());


        //////////////////////////////////////
        for(s2 = 0; s2 < sameXStripSegs.size(); s2++)//to every other segment in ring
		{
			//make sure its not the same segment
			if(s == s2)
			{continue;}
			
            thatSeg = sameXStripSegs[s2];
			if(thatSeg->trailingSeg)//already connected to a trailing segment...
				continue;
			
			thatPoint = &thatSeg->p1;//to the first point of "that" segment
            if(IsZero(Distance2D(*thisPoint, *thatPoint),0.03))//they are close enough to each other
            {
				potentialLeadSegs.push_back(thatSeg);
            }
		}
        //////////////////////////////////////

		//sort through and pick from the potential pile
		//we want to pick a segment with the sharpest change in direction!
		//
		//
		//1>>>>>>>>>A>>>>>>>>2 1>>>>>>>>B>>>>>>>>>2
		//                    ^
		//             large delta angle/ Right Wieghted
		minDist = 100000.0;
		finalLeadSeg = NULL;
		potentialangle = 0.0;
		for(potential = 0; potential < potentialLeadSegs.size(); potential++)
		{
			thatSeg = potentialLeadSegs[potential];
			//potentialDot = (thisSeg->normal.x() * thatSeg->normal.x()) + (thisSeg->normal.y() * thatSeg->normal.y()); //gives a number indicating how sharp the angle is, -1 is the sharpest (-1,1)
			//potentialCross = (thisSeg->normal.x() * thatSeg->normal.y()) - (thisSeg->normal.y() * thatSeg->normal.x());//gives a number indicating a right or left turn. (uphill is positive), (downhill is negative) (-1,1)
			potentialDist = Distance2D(thisSeg->p2, thatSeg->p1);
			
			if(potentialDist < minDist)
			{
				minDist = potentialDist;
				finalLeadSeg = potentialLeadSegs[potential];
			}
			
		}
		if(finalLeadSeg)
		{
			thisSeg->leadingSeg = finalLeadSeg;
			finalLeadSeg->trailingSeg = thisSeg;

			thisSeg->p2 = finalLeadSeg->p1;
			thisSeg->FormNormal();
		}
	}
}
Beispiel #27
0
long gauss(mat_zz_pE& M_in, long w)
{
   long k, l;
   long i, j;
   long pos;
   zz_pX t1, t2, t3;
   zz_pX *x, *y;

   long n = M_in.NumRows();
   long m = M_in.NumCols();

   if (w < 0 || w > m)
      Error("gauss: bad args");

   const zz_pXModulus& p = zz_pE::modulus();


   vec_zz_pX *M = newNTL_NEW_OP vec_zz_pX[n];

   for (i = 0; i < n; i++) {
      M[i].SetLength(m);
      for (j = 0; j < m; j++) {
         M[i][j].rep.SetMaxLength(2*deg(p)-1);
         M[i][j] = rep(M_in[i][j]);
      }
   }

   l = 0;
   for (k = 0; k < w && l < n; k++) {

      pos = -1;
      for (i = l; i < n; i++) {
         rem(t1, M[i][k], p);
         M[i][k] = t1;
         if (pos == -1 && !IsZero(t1)) {
            pos = i;
         }
      }

      if (pos != -1) {
         swap(M[pos], M[l]);

         InvMod(t3, M[l][k], p);
         negate(t3, t3);

         for (j = k+1; j < m; j++) {
            rem(M[l][j], M[l][j], p);
         }

         for (i = l+1; i < n; i++) {
            // M[i] = M[i] + M[l]*M[i,k]*t3

            MulMod(t1, M[i][k], t3, p);

            clear(M[i][k]);

            x = M[i].elts() + (k+1);
            y = M[l].elts() + (k+1);

            for (j = k+1; j < m; j++, x++, y++) {
               // *x = *x + (*y)*t1

               mul(t2, *y, t1);
               add(t2, t2, *x);
               *x = t2;
            }
         }

         l++;
      }
   }
   
   for (i = 0; i < n; i++)
      for (j = 0; j < m; j++)
         conv(M_in[i][j], M[i][j]);

   delete [] M;

   return l;
}
Beispiel #28
0
int MathUtils::solveCubic(double c[4], double s[3]) {
    int     i, num;
    double  sub;
    double  A, B, C;
    double  sq_A, p, q;
    double  cb_p, D;

    /* normal form: x^3 + Ax^2 + Bx + C = 0 */

    A = c[ 2 ] / c[ 3 ];
    B = c[ 1 ] / c[ 3 ];
    C = c[ 0 ] / c[ 3 ];

    /*  substitute x = y - A/3 to eliminate quadric term:
	x^3 +px + q = 0 */

    sq_A = A * A;
    p = 1.0/3 * (- 1.0/3 * sq_A + B);
    q = 1.0/2 * (2.0/27 * A * sq_A - 1.0/3 * A * B + C);

    /* use Cardano's formula */

    cb_p = p * p * p;
    D = q * q + cb_p;

    if (IsZero(D)) {
		if (IsZero(q)) { /* one triple solution */
		    s[ 0 ] = 0;
		    num = 1;
		}
	else { /* one single and one double solution */
	    double u = cbrt(-q);
	    s[ 0 ] = 2 * u;
	    s[ 1 ] = - u;
	    num = 2;
	}
    }
    else if (D < 0) { /* Casus irreducibilis: three real solutions */
		double phi = 1.0/3 * acos(-q / sqrt(-cb_p));
		double t = 2 * sqrt(-p);

		s[ 0 ] =   t * cos(phi);
		s[ 1 ] = - t * cos(phi + M_PI / 3);
		s[ 2 ] = - t * cos(phi - M_PI / 3);
		num = 3;
    }
    else { /* one real solution */
		double sqrt_D = sqrt(D);
		double u = cbrt(sqrt_D - q);
		double v = - cbrt(sqrt_D + q);

		s[ 0 ] = u + v;
		num = 1;
    }

    /* resubstitute */

    sub = 1.0/3 * A;

    for (i = 0; i < num; ++i)
	s[ i ] -= sub;

    return num;
}
int SolveQuartic(double *c, double *s)
{
    double  coeffs[ 4 ];
    double  z, u, v, sub;
    double  A, B, C, D;
    double  sq_A, p, q, r;
    int     i, num;

    /* normal form: x^4 + Ax^3 + Bx^2 + Cx + D = 0 */

    A = c[ 3 ] / c[ 4 ];
    B = c[ 2 ] / c[ 4 ];
    C = c[ 1 ] / c[ 4 ];
    D = c[ 0 ] / c[ 4 ];

    /*  substitute x = y - A/4 to eliminate cubic term:
	x^4 + px^2 + qx + r = 0 */

    sq_A = A * A;
    p = - 3.0/8 * sq_A + B;
    q = 1.0/8 * sq_A * A - 1.0/2 * A * B + C;
    r = - 3.0/256*sq_A*sq_A + 1.0/16*sq_A*B - 1.0/4*A*C + D;

    if (IsZero(r))
    {
	/* no absolute term: y(y^3 + py + q) = 0 */

	coeffs[ 0 ] = q;
	coeffs[ 1 ] = p;
	coeffs[ 2 ] = 0;
	coeffs[ 3 ] = 1;

	num = SolveCubic(coeffs, s);

	s[ num++ ] = 0;
    }
    else
    {
	/* solve the resolvent cubic ... */

	coeffs[ 0 ] = 1.0/2 * r * p - 1.0/8 * q * q;
	coeffs[ 1 ] = - r;
	coeffs[ 2 ] = - 1.0/2 * p;
	coeffs[ 3 ] = 1;

	(void) SolveCubic(coeffs, s);

	/* ... and take the one real solution ... */

	z = s[ 0 ];

	/* ... to build two quadric equations */

	u = z * z - r;
	v = 2 * z - p;

	if (IsZero(u))
	    u = 0;
	else if (u > 0)
	    u = sqrt(u);
	else
	    return 0;

	if (IsZero(v))
	    v = 0;
	else if (v > 0)
	    v = sqrt(v);
	else
	    return 0;

	coeffs[ 0 ] = z - u;
	coeffs[ 1 ] = q < 0 ? -v : v;
	coeffs[ 2 ] = 1;

	num = SolveQuadric(coeffs, s);

	coeffs[ 0 ]= z + u;
	coeffs[ 1 ] = q < 0 ? v : -v;
	coeffs[ 2 ] = 1;

	num += SolveQuadric(coeffs, s + num);
    }

    /* resubstitute */

    sub = 1.0/4 * A;

    for (i = 0; i < num; ++i)
	s[ i ] -= sub;

    return num;
}
Beispiel #30
0
static FeatureData
Combine_Line_Line_Constraints(FeaturePtr c1, FeaturePtr c2)
{
	Vector		cross;
	double		param1;
	Vector		temp_v1, temp_v2, temp_v3, temp_v4;
	Vector		point1;
	FeatureData	result;

	/* The result is inconsistent if the lines don't intersect, a point
	** otherwise (their point of intersection.
	*/

	VCross(c1->f_vector, c2->f_vector, cross);

	if ( VZero(cross) )
	{
		/* The lines are parallel. */
		if ( Point_On_Line( c1->f_vector, c1->f_point,
							c2->f_point) )
			return *c1;
		else
		{
			result.f_type = inconsistent_feature;
			return result;
		}
	}

	/* They still may or may not intersect. */
	VSub(c1->f_point, c2->f_point, temp_v1);
	VCross(c2->f_vector, temp_v1, temp_v2);
	VCross(c1->f_vector, temp_v1, temp_v3);

	/* temp_v3 and temp_v2 are both perp to temp_v1. */
	/* If temp_v2 is 0, then the lines intersect at c1->f_point1. */
	/* If temp_v3 is 0, then the lines intersect at c1->f_point2. */
	/* If temp_v2 and temp_v3 are parallel, the lines intersect somewhere. */
	/* Otherwise they don't. */
	if ( VZero(temp_v2) )
	{
		result.f_type = point_feature;
		result.f_point = c1->f_point;
		return result;
	}
	else if ( VZero(temp_v2) )
	{
		result.f_type = point_feature;
		result.f_point = c2->f_point;
		return result;
	}

	VCross(temp_v2, temp_v3, temp_v4);
	if ( ! VZero(temp_v4) )
	{
		result.f_type = inconsistent_feature;
		return result;
	}


	/* Get the parameter for the point of intersection. */
	if ( ! IsZero(cross.z) )
		param1 = temp_v2.z / cross.z;
	else if ( ! IsZero(cross.y) )
		param1 = temp_v2.y / cross.y;
	else
		param1 = temp_v2.x / cross.x;

	VScalarMul(c1->f_vector, param1, temp_v1);
	VAdd(temp_v1, c1->f_point, point1);

	result.f_type = point_feature;
	result.f_point = point1;
	return result;
}