Esempio n. 1
0
void inverse( double** a, int nRows, int nCols)
{
	int i,j,k;
	double* w = new double[nCols];
	double** v = allocate2DDouble( nRows, nCols);
	double** temp = allocate2DDouble( nRows, nCols );
	for( i=0; i<nRows; i++)
		memset( v[i], 0, sizeof(double) * nCols );
	memset( w, 0, sizeof(double) * nCols );

	// SVD
	copyMatrix( a, temp, nRows, nCols);
	svdcmp(temp, nRows, nCols, w, v); 

	for( i=0; i<nCols; i++)
	{
		if( !nearzero( w[i] ) )
			w[i] = 1.0 / w[i];
	}

	for( i=0; i<nCols; i++)
		for( j=0; j<nRows; j++)
		{
			temp[j][i] = temp[j][i] * w[i]; 
		}

	for( i=0; i<nRows; i++)
		memset( a[i], 0, sizeof(double) * nCols );

	for( i=0; i<nRows; i++)
		for( j=0; j<nCols; j++)
			for( k=0; k<nCols; k++)
			{
				a[i][j] += temp[i][k] * v[j][k];		// coz' v is not transposed  
			}


	SAFEDELARR( w );
	if( v != NULL )
	{
		for( i=0; i<nRows; i++ )
			SAFEDELARR( v[i] );
		SAFEDELARR( v );
	}
	if( temp != NULL )
	{
		for( i=0; i<nRows; i++ )
			SAFEDELARR( temp[i] );
		SAFEDELARR( temp );
	}
}
Esempio n. 2
0
//
// R_classifyDynaSeg
//
// The seg is either left, right, or on the partition line.
//
static int R_classifyDynaSeg(const dynaseg_t *part, const dynaseg_t *seg, double pdx, double pdy)
{
   double dx2, dy2, dx3, dy3, a, b;

   // check line against partition
   dx2 = part->psx - seg->psx;
   dy2 = part->psy - seg->psy;
   dx3 = part->psx - seg->pex;
   dy3 = part->psy - seg->pey;

   a = pdy * dx2 - pdx * dy2;
   b = pdy * dx3 - pdx * dy3;

   if(!(a*b >= 0) && !nearzero(a) && !nearzero(b))
   {
      double x = 0.0, y = 0.0;

      // line is split
      R_ComputeIntersection(part, seg, x, y);

      // find distance from line start to split point
      dx2 = seg->psx - x;
      dy2 = seg->psy - y;
      
      if(nearzero(dx2) && nearzero(dy2))
         a = 0.0;
      else
      {
         double l = dx2*dx2 + dy2*dy2;
         if(l < 4.0)
            a = 0.0;
      }

      dx3 = seg->pex - x;
      dy3 = seg->pey - y;

      if(nearzero(dx3) && nearzero(dy3))
         b = 0.0;
      else
      {
         double l = dx3*dx3 + dy3*dy3;
         if(l < 4.0)
            b = 0.0;
      }
   }

   int val = 0;

   if(nearzero(a))   // start is on the partition
      val |= START_ON;
   else if(a < 0.0)  // start is on left
      val |= START_LEFT;
   else              // start is on right
      val |= START_RIGHT;

   if(nearzero(b))   // end is on partition
      val |= END_ON;
   else if(b < 0.0)  // end is on left
      val |= END_LEFT;
   else              // end is on right
      val |= END_RIGHT;

   return val;
}
Esempio n. 3
0
//
// R_selectPartition
//
// This routine decides the best dynaseg to use as a nodeline by attempting to
// minimize the number of splits it would cause in remaining dynasegs.
//
// Credit to Raphael Quinet and DEU.
//
// Rewritten by Lee Killough for significant performance increases.
//  (haleyjd - using gotos, naturally ;)
//
static dynaseg_t *R_selectPartition(dseglist_t segs)
{
   dseglink_t *rover;
   dynaseg_t *best = NULL;
   int bestcost = INT_MAX;
   int cnt = 0;

   // count the number of segs on the input list
   for(rover = segs; rover; rover = rover->dllNext)
      ++cnt;

   // Try each seg as a partition line
   for(rover = segs; rover; rover = rover->dllNext)
   {
      dynaseg_t  *part = *rover;
      dseglink_t *crover;
      int cost = 0, tot = 0, diff = cnt;

      // haleyjd: add one seg worth of cost to non-orthogonal lines
      if(part->seg.linedef->slopetype > ST_VERTICAL)
         cost += FACTOR;

      // Check partition against all segs
      for(crover = segs; crover; crover = crover->dllNext)
      {
         dynaseg_t *check = *crover;

         // classify both end points
         double a = part->pdy * check->psx - part->pdx * check->psy + part->ptmp;
         double b = part->pdy * check->pex - part->pdx * check->pey + part->ptmp;

         if(!(a*b >= 0)) // oppositely signed?
         {
            if(!nearzero(a) && !nearzero(b)) // not within epsilon of 0?
            {
               // line is split
               double l = check->len;
               double d = (l * a) / (a - b); // distance from intersection

               if(d >= 2.0)
               {
                  cost += FACTOR;

                  // killough: This is the heart of my pruning idea - it 
                  // catches bad segs early on.
                  if(cost > bestcost)
                     goto prune;

                  ++tot;
               }
               else if(l - d < 2.0 ? check->pdx * part->pdx + check->pdy * part->pdy < 0 : b < 0)
                  goto leftside;
            }
            else
               goto leftside;
         }
         else if(a <= 0 && (!nearzero(a) || 
            (nearzero(b) && check->pdx * part->pdx + check->pdy * part->pdy < 0)))
         {
leftside:
            diff -= 2;
         }
      } // end for

      // Take absolute value; diff is being used to obtain the min/max values
      // by way of min(a, b) = (a + b - abs(a - b)) / 2
      if((diff -= tot) < 0)
         diff = -diff;

      // Make sure at least one seg is on each side of the partition
      if(tot + cnt > diff && (cost += diff) < bestcost)
      {
         // we have a new better choice
         bestcost = cost;
         best = part;     // remember the best seg
      }
prune: ; // early exit and skip past the tests above
   } // end for

   // haleyjd: failsafe. Maybe there's just one left in the list. I'm not
   // taking any chances that the above algorithm might freak out when that
   // becomes the case. I KNOW the list is not empty.
   if(!best)
      best = *segs;

   return best; // All finished, return best seg
}