Beispiel #1
0
void callFFTN(double          *data, 
	      size_t              K,
	      const mwSize       *N,
	      double        **sol_r,
	      double        **sol_i
	      )
{
  mxArray *F,*f;
  mxArray *LHS[1];
  int N1 = N[0];
  int N2 = N[1];

  f = mxCreateNumericArray(K,N,mxDOUBLE_CLASS,mxCOMPLEX);
  memcpy(mxGetPr(f),data,sizeof(double)*N1*N2);
  mexCallMATLABWithTrap(1,LHS,1,&f,"fftn");

  F = LHS[0];

  *sol_r = (double *)mxGetData(F);
  *sol_i = (double *)mxGetImagData(F);
  
  DisplayMatrix("F",mxGetPr(F),mxGetPi(F),N1,N2);

  mxDestroyArray(f);
  //  mxDestroyArray(F);  
}
int32 CVICALLBACK callbackWrapper(TaskHandle taskHandle, int32 eventInfo, void *callbackData)
{
	CallbackData *cbData = (CallbackData*)callbackData;

	mxArray *rhs[3];
	rhs[1] = cbData->taskObjHandle;
	rhs[2] = cbData->eventData;
	
#if DEBUG_MEX
	mexPrintf("in CBWrap\n");
#endif

	int32 retval = 0;
	size_t cachedNCB = cbData->numCallbacks; // veej wants deletion of a task object during a DONE callback to work
	const char *cachedCBT = cbData->callbackType; 
	for (size_t i=0;i<cachedNCB;i++){
#if DEBUG_MEX
	mexPrintf("in CBWrap, calling %d\n",i);
#endif
		//mException = mexCallMATLABWithTrap(0,NULL,0,0,cbData->callbackFuncNames[i]); //TODO -- pass arguments!
		rhs[0] = cbData->callbackFuncHandles[i];
		mxArray *mException = mexCallMATLABWithTrap(0,NULL,3,rhs,"feval"); //TODO -- pass arguments!
		if (!mException) {
			continue;
		} else {
			char *errorString = (char*)mxCalloc(256,sizeof(char));
			mxGetString(mxGetProperty(mException,0,"message"),errorString,MAXCALLBACKNAMELENGTH);
			mexPrintf("ERROR in %s callback of Task object: %s\n",cachedCBT,errorString);
			mxFree(errorString);
			retval = 1;
			break;
		}
	}

	return retval;
}
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){ ALLOCATES();

  CreateTicTacToc( CallMatlab );
  CreateTicTacToc( callSort   );
  int               I, J, K, ii, jj, kk;
  int               IJ, IJK, IJK_1;
  int               DI, DJ, DK, DIJK, DIJK_1;
  int               CDI, CDJ, CDK;
  int               result, fevals = 0;
  int               NVOLS, NVOLS_1, n, s, s_start, s_end, v_init;
  real              *volumes, *V, x, y, *DIST, *order, last_distance;
  int               *VV=NULL, nV, v, vv;
  char              skip;
  triplet           *TS=NULL, *DTS=NULL, T;
  mxArray           *INPUT[2]={NULL,NULL}, *OUTPUT[3]={NULL,NULL,NULL};
  double            *MAXs, LAST_MAX;
  double            thisMINx, thisMINy;
  double            *idxs;
  double            *vols;
  double            *ijk;
  char              callSort;
  mwSize            toVec[2]={1,1};
  char              VERBOSE = 0;
  char              STR[1024];
  
  
  if( nlhs > 1 ){
    mxErrMsgTxt("too much outputs");
  }


  if( mxIsChar( prhs[nrhs-1] ) ){
    mxGetString( prhs[nrhs-1], STR, 100 );
    if( ! myStrcmpi(STR,"verbose") ){ 
      VERBOSE = 1;
    } else {
      mxErrMsgTxt("only 'verbose' option allowed.");
    }
    nrhs = nrhs-1;
  }
  
  
  if( nrhs != 3 ){
    mxErrMsgTxt("sintax error. max_min_multiples_erodes( V , F , volumes )");
  }

  if( mxGetClassID( prhs[1] ) != mxFUNCTION_CLASS ){
    mxErrMsgTxt("F have to be a function_handle.");
  }

  if( myNDims( prhs[0] ) > 3  ){
    mxErrMsgTxt("bigger than 3d arrays is not allowed.");
  }
  
  NVOLS   = myNumel( prhs[2] );
  NVOLS_1 = NVOLS - 1;
  volumes = myGetPr( prhs[2] );
  
  
  I     = mySize( prhs[0] , 0 );
  J     = mySize( prhs[0] , 1 );
  K     = mySize( prhs[0] , 2 );
  IJ    = I*J;
  IJK   = IJ*K;
  

  VV = (int     *) mxMalloc( IJK*sizeof( int     ) );
  TS     = (triplet *) mxMalloc( IJK*sizeof( triplet ) );

  V = myGetPr( prhs[0] );

  v  = 0; 
  nV = 0;
  for( kk = 0 ; kk < K ; kk++ ){ for( jj = 0 ; jj < J ; jj++ ){ for( ii = 0 ; ii < I ; ii++ ){
    x = V[ v ];
    if( x == x ){
      VV[ nV ] = v;
      TS[ v ].isnan = 0;
      TS[ v ].i     = ii;
      TS[ v ].j     = jj;
      TS[ v ].k     = kk;
      nV++;
    } else {
      TS[ v ].isnan = 1;
    }
    v++;
  }}}


  INPUT[0] = prhs[1];
  INPUT[1] = mxCreateNumericMatrix( 1 , 3 , mxDOUBLE_CLASS , mxREAL );
  ijk = (double *) mxGetData( INPUT[1] );
  
  
  ijk[0] = TS[ VV[ nV/2] ].i + 1;
  ijk[1] = TS[ VV[ nV/2] ].j + 1;
  ijk[2] = TS[ VV[ nV/2] ].k + 1;
  


  OUTPUT[2] = mexCallMATLABWithTrap( 2 , OUTPUT , 2 , INPUT , "feval" );
  
  if( OUTPUT[2] == NULL ){
    
    callSort = 0;
    if( mxGetClassID( OUTPUT[0] ) != mxDOUBLE_CLASS ){
      if( INPUT[1]  != NULL ){ mxDestroyArray( INPUT[1] );  INPUT[1]=NULL;  }
      if( OUTPUT[0] != NULL ){ mxDestroyArray( OUTPUT[0] ); OUTPUT[0]=NULL; }
      if( OUTPUT[1] != NULL ){ mxDestroyArray( OUTPUT[1] ); OUTPUT[1]=NULL; }
      if( OUTPUT[2] != NULL ){ mxDestroyArray( OUTPUT[2] ); OUTPUT[2]=NULL; }
      mxErrMsgTxt("F debe retornar un double en el primer output.");
    }
    if( mxGetClassID( OUTPUT[1] ) != mxDOUBLE_CLASS ){
      if( INPUT[1]  != NULL ){ mxDestroyArray( INPUT[1] );  INPUT[1]=NULL;  }
      if( OUTPUT[0] != NULL ){ mxDestroyArray( OUTPUT[0] ); OUTPUT[0]=NULL; }
      if( OUTPUT[1] != NULL ){ mxDestroyArray( OUTPUT[1] ); OUTPUT[1]=NULL; }
      if( OUTPUT[2] != NULL ){ mxDestroyArray( OUTPUT[2] ); OUTPUT[2]=NULL; }
      mxErrMsgTxt("F debe retornar un double en el segundo output.");
    }
    
  } else {

    callSort = 1;
    if( VERBOSE ){
      mexPrintf("sort has to be called\n");
    }
    
    mxDestroyArray( OUTPUT[2] ); OUTPUT[2] = NULL;

    result = mexCallMATLAB( 1 , OUTPUT , 2 , INPUT , "feval" );
    if( result ){ mxErrMsgTxt("error computing la funcion."); }

    if( mxGetClassID( OUTPUT[0] ) != mxDOUBLE_CLASS ){
      if( INPUT[1]  != NULL ){ mxDestroyArray( INPUT[1] );  INPUT[1]=NULL;  }
      if( OUTPUT[0] != NULL ){ mxDestroyArray( OUTPUT[0] ); OUTPUT[0]=NULL; }
      if( OUTPUT[1] != NULL ){ mxDestroyArray( OUTPUT[1] ); OUTPUT[1]=NULL; }
      if( OUTPUT[2] != NULL ){ mxDestroyArray( OUTPUT[2] ); OUTPUT[2]=NULL; }
      mxErrMsgTxt("F debe retornar un double en el primer output.");
    }

  }

  DI   = mySize( OUTPUT[0] , 0 );
  DJ   = mySize( OUTPUT[0] , 1 );
  DK   = mySize( OUTPUT[0] , 2 );
  
  DTS  = (triplet *) mxMalloc( 2*DI*DJ*DK*sizeof( triplet ) );
  

  plhs[0] = mxCreateNumericMatrix( NVOLS , 1 , mxREAL_CLASS , mxREAL );
  MAXs    = (real *) mxGetData( plhs[0] );
  for( n = 0 ; n < NVOLS ; n++ ){
    MAXs[n] = -10000;
  }

  
  LAST_MAX = MAXs[ NVOLS_1 ];
  for( v_init = 0 ; v_init < EVERY ; v_init++ ){
    if( utIsInterruptPending() ){
      if( INPUT[1]  != NULL ){ mxDestroyArray( INPUT[1] );  INPUT[1]=NULL;  }
      if( OUTPUT[0] != NULL ){ mxDestroyArray( OUTPUT[0] ); OUTPUT[0]=NULL; }
      if( OUTPUT[1] != NULL ){ mxDestroyArray( OUTPUT[1] ); OUTPUT[1]=NULL; }
      if( OUTPUT[2] != NULL ){ mxDestroyArray( OUTPUT[2] ); OUTPUT[2]=NULL; }
      mexPrintf("USER INTERRUP!!!\n");
      mxErrMsgTxt("USER INTERRUP!!!");
    }
    if( VERBOSE ){
      mexPrintf("v_init:  %d  (%g)  of  %d\n", v_init , LAST_MAX , EVERY );
    }

    for( v = v_init ; v < nV ; v += EVERY ){
      vv = VV[ v ];
      
      thisMINx =   V[ vv ];
      thisMINy =  -thisMINx;
      if( ( thisMINx < LAST_MAX )  && ( thisMINy < LAST_MAX ) ){
        continue;
      }

      T = TS[ vv ];
      
      ijk[0] = T.i + 1;
      ijk[1] = T.j + 1;
      ijk[2] = T.k + 1;
      

      if( OUTPUT[0] != NULL ){ mxDestroyArray( OUTPUT[0] ); OUTPUT[0]=NULL; }
      if( OUTPUT[1] != NULL ){ mxDestroyArray( OUTPUT[1] ); OUTPUT[1]=NULL; }
      if( OUTPUT[2] != NULL ){ mxDestroyArray( OUTPUT[2] ); OUTPUT[2]=NULL; }

      if( !callSort ){
        tic( CallMatlab );
        result = mexCallMATLAB( 2 , OUTPUT , 2 , INPUT , "feval" ); fevals++;
        tac( CallMatlab );
      } else {
        tic( CallMatlab );
        result = mexCallMATLAB( 1 , OUTPUT , 2 , INPUT , "feval" ); fevals++;
        tac( CallMatlab );
      }
      
      DI   = mySize( OUTPUT[0] , 0 );
      DJ   = mySize( OUTPUT[0] , 1 );
      DK   = mySize( OUTPUT[0] , 2 );

      DIJK    = DI*DJ*DK;

      if( volumes[ NVOLS_1 ] > DIJK ){
      if( INPUT[1]  != NULL ){ mxDestroyArray( INPUT[1] );  INPUT[1]=NULL;  }
      if( OUTPUT[0] != NULL ){ mxDestroyArray( OUTPUT[0] ); OUTPUT[0]=NULL; }
      if( OUTPUT[1] != NULL ){ mxDestroyArray( OUTPUT[1] ); OUTPUT[1]=NULL; }
      if( OUTPUT[2] != NULL ){ mxDestroyArray( OUTPUT[2] ); OUTPUT[2]=NULL; }
        mxErrMsgTxt("el maximo volumen debe ser menor que numel(DIST)");
      }

      DIJK_1  = DIJK - 1;

      DIST  = (double  *) mxGetData( OUTPUT[0] );
      
      DTS  = (triplet *) mxRealloc( DTS , DIJK*sizeof( triplet ) );
      s = 0;
      for( kk = 0 ; kk < DK ; kk++ ){ for( jj = 0 ; jj < DJ ; jj++ ){ for( ii = 0 ; ii < DI ; ii++ ){
        DTS[ s ].i = ii;
        DTS[ s ].j = jj;
        DTS[ s ].k = kk;
        s++;
      }}}


      if( !callSort ){
        order = (double  *) mxGetData( OUTPUT[1] );
      } else {
        toVec[0] = mxGetNumberOfElements( OUTPUT[0] );
        mxSetDimensions( OUTPUT[0] ,  toVec  , 2 );
        
        tic( callSort );
        result = mexCallMATLAB( 2 , OUTPUT+1 , 1 , OUTPUT , "sort" );
        tac( callSort );
      
        order = (double  *) mxGetData( OUTPUT[2] );
      }
      
      CDI = DTS[ (int) ( order[0] - 1 ) ].i;
      CDJ = DTS[ (int) ( order[0] - 1 ) ].j;
      CDK = DTS[ (int) ( order[0] - 1 ) ].k;
      
      
      skip   = 0;

      s = 0;
      for( n = 0 ; n < NVOLS ; n++ ){
        s_end = (int) ( volumes[n] - 1 );
        last_distance = DIST[ (int) order[ s_end ] - 1 ];
        
        while( s_end < DIJK_1 && DIST[ (int) ( order[ s_end + 1 ] - 1 ) ] == last_distance ){
          s_end++;
        }
        s_end++;
        
        for( ; s < s_end ; s++ ){
          vv = (int) ( order[ s ] - 1 );
          
          ii = T.i + DTS[ vv ].i - CDI;  if( ii < 0 || ii > I ){ skip = 1; break; }
          jj = T.j + DTS[ vv ].j - CDJ;  if( jj < 0 || jj > J ){ skip = 1; break; }
          kk = T.k + DTS[ vv ].k - CDK;  if( kk < 0 || kk > K ){ skip = 1; break; }
            
          vv = ii + jj*I + kk*IJ;
          if( TS[ vv ].isnan ){  skip = 1; break; }
          x =  V[ vv ];  if( x < thisMINx ){ thisMINx = x; }
          y = -x;        if( y < thisMINy ){ thisMINy = y; }
          if( ( thisMINx < LAST_MAX )  && ( thisMINy < LAST_MAX ) ){
            skip = 1; break; 
          }
        }
        if( skip ){  break; }
        if( thisMINx > MAXs[n] ){ MAXs[n] = thisMINx; }
        if( thisMINy > MAXs[n] ){ MAXs[n] = thisMINy; }
      }
      LAST_MAX = MAXs[ NVOLS_1 ];

    }
    
  }
  if( INPUT[1]  != NULL ){ mxDestroyArray( INPUT[1]  ); INPUT[1] =NULL; }
  if( OUTPUT[0] != NULL ){ mxDestroyArray( OUTPUT[0] ); OUTPUT[0]=NULL; }
  if( OUTPUT[1] != NULL ){ mxDestroyArray( OUTPUT[1] ); OUTPUT[1]=NULL; }
  if( OUTPUT[2] != NULL ){ mxDestroyArray( OUTPUT[2] ); OUTPUT[2]=NULL; }
  
  if( VERBOSE ){
    mexPrintf( "\nfevals: %d  en  tiempo:   CallMatlab: %20.30g    sorting: %20.30g\n" , fevals , toc( CallMatlab ) , toc( callSort ) );
  }
  
  
  if(  VV != NULL ){  mxFree(  VV ); }
  if(  TS != NULL ){  mxFree(  TS ); }
  if( DTS != NULL ){  mxFree( DTS ); }

  myFreeALLOCATES();

}
int mxToBytes(const mxArray *mx, char *byteArray, int byteArrayLength) {
    int ii;
    int nInfoBytes=0, nDataBytes=0, nFreeBytes=0;
    mxGramInfo info;
    
    // for complex types
    int jj;
    int nElements;
    mxArray *elementData, *elementName;
    char *elementByteArray;
    int elementGramLength;
    
    mxArray *callMatlabError;
    
    if (mx == NULL)
        return(0);
    
    info.gramBytes = byteArray;
    setInfoFieldsFromMx(&info, mx);
    
    info.dataBytes = byteArray + MX_GRAM_OFFSET_DATA;
    nFreeBytes = byteArrayLength - MX_GRAM_OFFSET_DATA;
    
    if (info.gramType==mxGramDouble) {
        nDataBytes = writeMxDoubleDataToBytes(mx, &info, nFreeBytes);
        
    } else if (info.gramType==mxGramChar) {
        nDataBytes = writeMxCharDataToBytes(mx, &info, nFreeBytes);
        
    } else if (info.gramType==mxGramLogical) {
        nDataBytes = writeMxLogicalDataToBytes(mx, &info, nFreeBytes);
        
    } else if (info.gramType==mxGramCell) {
        // recur to write data for each cell element
        nElements = info.dataM * info.dataN;
        
        elementByteArray = info.dataBytes;
        elementGramLength = 0;
        for (ii=0; ii<nElements; ii++) {
            elementData = mxGetCell(mx, ii);
            elementGramLength = mxToBytes((const mxArray*)elementData, elementByteArray, nFreeBytes);
            
            if (elementGramLength < 0)
                return(elementGramLength);
            
            nDataBytes += elementGramLength;
            elementByteArray += elementGramLength;
            nFreeBytes -= elementGramLength;
        }
        
    } else if (info.gramType==mxGramStruct) {
        
        // struct arrays resized to 1xn, with m fields
        nElements = mxGetNumberOfFields(mx);
        info.dataM = nElements;
        info.dataN = mxGetM(mx) * mxGetN(mx);
        
        // recur to write data for each field name
        elementByteArray = info.dataBytes;
        elementGramLength = 0;
        for (ii=0; ii<nElements; ii++) {
            elementName = mxCreateString(mxGetFieldNameByNumber(mx, ii));
            elementGramLength = mxToBytes(elementName, elementByteArray, nFreeBytes);
            mxDestroyArray(elementName);
            
            if (elementGramLength < 0)
                return(elementGramLength);
            
            nDataBytes += elementGramLength;
            elementByteArray += elementGramLength;
            nFreeBytes -= elementGramLength;
        }
        
        // recur to write data for each field datum
        for (ii=0; ii<nElements; ii++) {
            for (jj=0; jj<info.dataN; jj++) {
                elementData = mxGetFieldByNumber(mx, jj, ii);
                elementGramLength = mxToBytes((const mxArray*)elementData, elementByteArray, nFreeBytes);
                
                if (elementGramLength < 0)
                    return(elementGramLength);
                
                nDataBytes += elementGramLength;
                elementByteArray += elementGramLength;
                nFreeBytes -= elementGramLength;
            }
        }
        
    } else if (info.gramType==mxGramFunctionHandle) {
        // recur to write stringified version of function
        callMatlabError = mexCallMATLABWithTrap(1, &elementData, 1, (mxArray**)&mx, MX_GRAM_FUNCTION_TO_STRING);
        if (callMatlabError == NULL && elementData != NULL) {
            nDataBytes = mxToBytes((const mxArray*)elementData, info.dataBytes, nFreeBytes);
            if (nDataBytes < 0)
                return(nDataBytes);
        } else
            return(-1);
        
    } else {
        return(mxGramUnsupported);
        
    }
    
    //mexPrintf("nDataBytes = %d\n", nDataBytes);
    if (nDataBytes < 0)
        return(nDataBytes);
    
    info.gramLength = MX_GRAM_OFFSET_DATA + nDataBytes;
    nInfoBytes = writeInfoFieldsToBytes(&info, byteArray, byteArrayLength);
    //mexPrintf("nInfoBytes = %d\n", nInfoBytes);
    //printMxGramInfo(&info);
    //printBytes(info.gramBytes, info.gramLength);
    return(info.gramLength);
}
int bytesToMx(mxArray **mx, const char *byteArray, int byteArrayLength) {
    int ii;
    int nInfoBytes=0, nFreeBytes=0, nBytesRead=0;
    mxGramInfo info;
    
    // for complex types
    int jj;
    int nElements;
    mxArray *elementData;
    mxArray *elementName;
    const char *elementByteArray;
    int elementBytesRead;
    char **fieldNames;
    
    mxArray *callMatlabError;
    
    info.gramBytes = (char *)byteArray;
    nInfoBytes = readInfoFieldsFromBytes(&info, byteArray, byteArrayLength);
    nBytesRead += nInfoBytes;
    
    info.dataBytes = (char *)byteArray + MX_GRAM_OFFSET_DATA;
    nFreeBytes = byteArrayLength - MX_GRAM_OFFSET_DATA;
    
    //printMxGramInfo(&info);
    //printBytes(info.gramBytes, info.gramLength);
    
    if (info.gramType==mxGramDouble) {
        *mx = mxCreateDoubleMatrix(info.dataM, info.dataN, mxREAL);
        nBytesRead += readMxDoubleDataFromBytes(*mx, &info, nFreeBytes);
        
    } else if (info.gramType==mxGramChar) {
        mwSize dims[2];
        dims[0] = info.dataM;
        dims[1] = info.dataN;
        *mx = mxCreateCharArray(2, dims);
        nBytesRead += readMxCharDataFromBytes(*mx, &info, nFreeBytes);
        
    } else if (info.gramType==mxGramLogical) {
        *mx = mxCreateLogicalMatrix(info.dataM, info.dataN);
        nBytesRead += readMxLogicalDataFromBytes(*mx, &info, nFreeBytes);
        
    } else if (info.gramType==mxGramCell) {
        *mx = mxCreateCellMatrix(info.dataM, info.dataN);
        
        nElements = info.dataM * info.dataN;
        elementByteArray = info.dataBytes;
        elementBytesRead = 0;
        
        for (ii=0; ii<nElements; ii++) {
            elementBytesRead = bytesToMx(&elementData, elementByteArray, nFreeBytes);
            if (elementBytesRead > 0) {
                mxSetCell(*mx, ii, elementData);
                nBytesRead += elementBytesRead;
                elementByteArray += elementBytesRead;
                nFreeBytes -= elementBytesRead;
            }
        }
        
    } else if (info.gramType==mxGramStruct) {
        
        // struct arrays may have size 1xn, with m fields
        nElements = info.dataM;
        fieldNames = mxMalloc(nElements*sizeof(char*));
        
        // recur to read out fieldNames
        elementByteArray = info.dataBytes;
        for (ii=0; ii<nElements; ii++) {
            elementBytesRead = bytesToMx(&elementName, elementByteArray, nFreeBytes);
            fieldNames[ii] = mxArrayToString(elementName);
            mxDestroyArray(elementName);
            
            nBytesRead += elementBytesRead;
            elementByteArray += elementBytesRead;
            nFreeBytes -= elementBytesRead;
        }
        
        *mx = mxCreateStructMatrix(1, info.dataN, info.dataM, (const char **)fieldNames);
        mxFree(fieldNames);
        
        // recur to fill in field data
        for (ii=0; ii<nElements; ii++) {
            for (jj=0; jj<info.dataN; jj++) {
                elementBytesRead = bytesToMx(&elementData, elementByteArray, nFreeBytes);
                mxSetFieldByNumber(*mx, jj, ii, elementData);
                
                nBytesRead += elementBytesRead;
                elementByteArray += elementBytesRead;
                nFreeBytes -= elementBytesRead;
            }
        }
        
    } else if (info.gramType==mxGramFunctionHandle) {
        // recur to read out stringified version of function
        elementBytesRead = bytesToMx(&elementData, info.dataBytes, nFreeBytes);
        if (elementBytesRead > 0) {
            nBytesRead += elementBytesRead;
            callMatlabError = mexCallMATLABWithTrap(1, mx, 1, &elementData, MX_GRAM_STRING_TO_FUNCTION);
        }
        
    } else {
        *mx = mxCreateDoubleScalar(-1);
        nBytesRead = 0;
    }
    
    return(nBytesRead);
}