⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 calcdhatsc.c

📁 一个计算多维定标(MDS)的matlab源代码
💻 C
字号:
#include "d:\matlab\extern\include\mex.h"
#include <math.h>
 
calcdhatsc( double *DH,
            int    ns,
			
            double *DO,
			
			double *inblock,
			double *ave,
			double *sum,
			double *nmem     )
{
  int     i,j,nblocks,blockactive,ups,downs,upa,reference,nmem1,nmem2,whatblock;
  double  value,av,sum1,sum2;

  /* Kruskal's upward-downward algorithm in C */

  /* start with the finest partition possible; every point is in one block */
  nblocks = ns;
  for (i=0; i<ns; i++)
  {
	 /* the inblock has a different interpretation from the MATLAB implementation:
	    every entry i in this array is filled with the block number that it is a member of */

	 *(inblock + i) = (double) i;
     value          = *( DO + i);
     /* square the distances */
	 
	 /*
	 *(ave	   + i) = value * value;
	 *(sum     + i) = value * value;
	 */

	 /* DO NOT square the distances */ 
	 *(ave	   + i) = value;
	 *(sum     + i) = value;

     *(nmem    + i) = (double) 1;
  }

  /* do the iterative process until the highest-block is up and down satisfied */
  blockactive  = 0;	/* in c, start with zero index */

  ups          = 0;
  downs        = 1;
  upa          = 1;

  while ((blockactive+1 < nblocks) || (ups==0) || (downs==0))
  { 
    /* is the current block up or downactive? */
    if (upa==1)
	{
       /* is the current block upsatisfied ? */
       ups = 1; /* assume it is satisfied */
       if (blockactive+1 < nblocks)
       {  
		  if ( *( ave+blockactive+1 ) < *( ave+blockactive ) )
          {
			 ups = 0;
          }
       }
      
       /* if the block is upsatisfied then the active block becomes downactive */
       if (ups == 1)
	   {
          upa = 0;
       }
		  else
	   {
	      /* if not, the active block is joined with the next higher block  */
          
          /* MATLAB code:
              members1 = B(blockactive).mem;
		      members2 = B(blockactive+1).mem;
              B(blockactive).mem  = union( members1 , members2 );

              the blocks with numbers "blockactive" and "blockactive+1" are joined
              in the block with number "blockactive";
              this means that all references to "blockactive+1 should now be changed to 
              blockactive
		  */

		  for (i=0; i<ns; i++)
          {
			  reference = (int) *( inblock+i );

              /* decrement all references higher than blockactive+1 */ 
              if (reference>=blockactive+1)
              {
				 *( inblock+i ) = (double) reference - 1;
              }
          }

          sum1     = *( sum+blockactive  );
          nmem1    = *( nmem+blockactive );
     
          sum2     = *( sum+blockactive+1);
          nmem2    = *( nmem+blockactive+1);
      
          *(sum+blockactive)  = sum1 + sum2;
          *(nmem+blockactive) = nmem1 + nmem2;
          *(ave+blockactive)  = (sum1 + sum2) / (nmem1 + nmem2);
      
          /* and now move all the blocks one downward */
          if (blockactive<=nblocks-3)
          {
             for (j=blockactive+1; j<=nblocks-2; j++)
             {
			   *( sum+j  ) = *( sum+j+1  );
			   *( ave+j  ) = *( ave+j+1  );
               *( nmem+j ) = *( nmem+j+1 );
             }
          }
         
          nblocks--;
          
          /* and the new, larger block becomes downactive */
          upa = 0;
		}
    }   
       else /* current block is downactive */
    {
       /* is the current block down satisfied ? */
       downs = 1; /* assume it is satisfied */
       if (blockactive > 0)
	   {
          if ( *( ave+blockactive-1 ) > *( ave+blockactive ) )
          {
             downs = 0;
          }
       }
      
       /* if the block is downsatisfied then the active block becomes upactive */
       if ( downs == 1 )
       {
          upa = 1;
       }
          else
       {
          /* if not, the active block is joined with the next lower block */
          
		  /* MATLAB code:
              members1 = B(blockactive).mem;
              members2 = B(blockactive-1).mem;
		      B(blockactive-1).mem  = union( members1 , members2 );

              decrement all references >= blockactive 
		  */

          for (i=0; i<ns; i++)
          {
			 reference = (int) *( inblock+i );

             if (reference >= blockactive)
             {
                *( inblock+i) = (double) reference-1;
             }
		  }

          sum1     = *(sum+blockactive);
          nmem1    = *(nmem+blockactive);
          
          sum2     = *(sum+blockactive-1);
          nmem2    = *(nmem+blockactive-1);
          
          *(sum+blockactive-1)  = sum1 + sum2;
          *(nmem+blockactive-1) = nmem1 + nmem2;
          *(ave+blockactive-1)  = (sum1 + sum2) / (nmem1 + nmem2);
      
          /* and now move all the blocks, including the active block one downward */
          if (blockactive<=nblocks-2)
          {
             for (j=blockactive; j<=nblocks-2; j++)
             {
                *( sum+j  ) = *( sum+j+1  );
 			    *( ave+j  ) = *( ave+j+1  );
                *( nmem+j ) = *( nmem+j+1 );
          	 }
          }
         
          blockactive--;
          nblocks--;
          
          /* and the new, larger block becomes upactive */
          upa = 1;
       }
    } 
   
    /* check whether the active block is simultaneously up and down satisfied */
    ups = 1; /* assume it is satisfied */
    if (blockactive+1 < nblocks)
    {
       if ( *( ave+blockactive+1 ) < *( ave+blockactive ) )
       {
          ups = 0;
       }
    }
   
    downs = 1; /* assume it is satisfied */
    if (blockactive > 0)
    {
       if ( *(ave+blockactive-1) > *( ave+blockactive ) )
       {
          downs = 0;
       }
    }
   
    if ((ups==1) && (downs==1))
    {
       /* both up and down-satisfied */
       if (blockactive+1 < nblocks)
       {
          /* transfer to next block */
          blockactive++;
          upa = 1;
       }
    }
  }   


  /* now, fill the DH-array with the block averages */
  for (i=0; i<ns; i++)
  {
    whatblock = (int) *( inblock+i );
    av = *( ave+whatblock );
    *( DH+i ) = av; 
  }

  /* and take the square root of the distances */
  /*
  for (i=0; i<ns; i++)
  {
    *( DH+i ) = sqrt( *( DH+i ) );
  }
  */
}


void mexFunction(  int nlhs, mxArray *plhs[],
				   int nrhs, const mxArray *prhs[] )

{
   double *DH;
   int    ns;
			
   double *DO;
			
   double *inblock;
   double *ave;
   double *sum;
   double *nmem;
   
   int    m,n;
   
   /* the input arguments are:
   0 = ns
   1 = DO
   
   the output arguments are
   0:  DH
   1:  inblock
   2:  ave
   3:  sum
   4:  nmem
   */

   if (nrhs != 2)
   {
      mexErrMsgTxt( "Only two input argument allowed." );
   }
      else if (nlhs != 5) 
   {
      mexErrMsgTxt( "Only five output argument allowed." );
   }
   
   /* the input ns must be a scalar */
   m = mxGetM( prhs[ 0 ] );
   n = mxGetN( prhs[ 0 ] );   
   if (!mxIsDouble( prhs[0]) || mxIsComplex(prhs[0]) || !(m ==1 && n==1)) mexErrMsgTxt("Input ns must be a scalar." );

   ns = mxGetScalar( prhs[ 0 ] );

   /* check the dimensions of the DO array */
   m = mxGetM( prhs[ 1 ] );
   n = mxGetN( prhs[ 1 ] );   
 
   if ((m != ns) || (n != 1)) mexErrMsgTxt("The DO Array has the wrong dimensions." );
   DO = mxGetPr( prhs[ 1 ] );

   /* the output arguments are
   0:  DH
   1:  inblock
   2:  ave
   3:  sum
   4:  nmem

   /* Create matrixes for the two return arguments. */   
   plhs[ 0 ] = mxCreateDoubleMatrix( ns,1, mxREAL );
   plhs[ 1 ] = mxCreateDoubleMatrix( ns,1, mxREAL );
   plhs[ 2 ] = mxCreateDoubleMatrix( ns,1, mxREAL );
   plhs[ 3 ] = mxCreateDoubleMatrix( ns,1, mxREAL );
   plhs[ 4 ] = mxCreateDoubleMatrix( ns,1, mxREAL );
   
   DH      = mxGetPr( plhs[ 0 ] );
   inblock = mxGetPr( plhs[ 1 ] );
   ave     = mxGetPr( plhs[ 2 ] );
   sum     = mxGetPr( plhs[ 3 ] );
   nmem    = mxGetPr( plhs[ 4 ] );
   
   /* call the subroutine */
   calcdhatsc( DH,ns,DO,inblock,ave,sum,nmem );
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -