如何编写这个c文件的mexFunction

时间:2014-03-19 22:37:29

标签: c matlab

该功能为cyclic.c

  void cyclic(float a[], float b[], float c[], float alpha, float beta,
    float r[], float x[], unsigned long n)

   // Solves for a vector x[1..n] the “cyclic” set of linear equations. a,
    //b, c, and r are input vectors, all dimensioned as [1..n], while alpha and beta are        //the corner
  //  entries in the matrix.

我是Matlab和C之间接口的新手。我已经好几年没用C了。 昨晚,我完成了它并编译。最后一件事就是召唤它。

#include "mex.h" 


#include "nrutil.h"

#define FREE_ARG char*
#define NR_END 1


#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#define NR_END 1
#define FREE_ARG char*
void nrerror(char error_text[])
/* Numerical Recipes standard error handler */
{fprintf(stderr,"Numerical Recipes run-time error...\n");
fprintf(stderr,"%s\n",error_text);
fprintf(stderr,"...now exiting to system...\n");
exit(1);
}
float *vector(long nl, long nh)
/* allocate a float vector with subscript range v[nl..nh] */
{
float *v;
v=(float *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(float)));
if (!v) nrerror("allocation failure in vector()");
return v-nl+NR_END;
}

void free_vector(float *v, long nl, long nh)
/* free a float vector allocated with vector() */
{
free((FREE_ARG) (v+nl-NR_END));
}

void tridag(float a[], float b[], float c[], float r[], float u[],
unsigned long n)
{
unsigned long j;
float bet,*gam;
gam=vector(1,n); 
if (b[1] == 0.0) nrerror("Error 1 in tridag");

u[1]=r[1]/(bet=b[1]);
for (j=2;j<=n;j++) {
gam[j]=c[j-1]/bet;
bet=b[j]-a[j]*gam[j];
if (bet == 0.0) nrerror("Error 2 in tridag"); 
        u[j]=(r[j]-a[j]*u[j-1])/bet; 
}
for (j=(n-1);j>=1;j--)
u[j] -= gam[j+1]*u[j+1]; 
free_vector(gam,1,n);
}


void cyclic(float a[], float b[], float c[], float alpha, float beta,
float r[], float x[], unsigned long n)

{
void tridag(float a[], float b[], float c[], float r[], float u[],
unsigned long n);
unsigned long i;
float fact,gamma,*bb,*u,*z;
if (n <= 2) nrerror("n too small in cyclic");
bb=vector(1,n);
u=vector(1,n);
z=vector(1,n);
gamma = -b[1]; //Avoid subtraction error in forming bb[1].
bb[1]=b[1]-gamma; //Set up the diagonal of the modified tridiagonal
bb[n]=b[n]-alpha*beta/gamma; //system.
for (i=2;i<n;i++) bb[i]=b[i];
tridag(a,bb,c,r,x,n);// Solve A · x = r.
u[1]=gamma;// Set up the vector u.
u[n]=alpha;
for (i=2;i<n;i++) u[i]=0.0;
tridag(a,bb,c,u,z,n);// Solve A · z = u.
fact=(x[1]+beta*x[n]/gamma)/ //Form v · x/(1 + v · z).
(1.0+z[1]+beta*z[n]/gamma);
for (i=1;i<=n;i++) x[i] -= fact*z[i]; //Nowget the solution vector x.
free_vector(z,1,n);
free_vector(u,1,n);
free_vector(bb,1,n);
}


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

   float *a,*b,*c,*x,*r;
   float alpha,beta;
unsigned long n = (unsigned long) mxGetScalar(prhs[6]);
 //   a=mxGetPr(prhs[0]); 
  //  b=mxGetPr(prhs[1]); 
  //  c=mxGetPr(prhs[2]);
  //  r=mxGetPr(prhs[5]);
    a = (float*) mxGetData(prhs[0]);
    b = (float*) mxGetData(prhs[1]);
    c = (float*) mxGetData(prhs[2]);
    r = (float*) mxGetData(prhs[5]);
   // alpha=*(mxGetPr(prhs[3]));
   // beta=*(mxGetPr(prhs[4]));
    alpha = (float) mxGetScalar(prhs[3]);
 beta = (float) mxGetScalar(prhs[4]);

    plhs[0]= mxCreateDoubleMatrix(n, 1, mxREAL);
    x = mxGetPr(plhs[0]);
    mexPrintf("%f  ",alpha); 
    mexPrintf("\n"); 
    mexPrintf("%f  ",beta); 
    mexPrintf("\n"); 
    mexPrintf("%d  ",n);
    mexPrintf("\n"); 

    cyclic(a,b,c, alpha, beta,r,x,n) ;
    mexPrintf("%d  ",n);
    mexPrintf("\n"); 
    } 

最后我成功编译了它cyclic(a,b,c, alpha, beta,r,x,n) ;。但答案是不对的。我认为这是因为r是一个虚构的向量。所以我的问题是如何在CMatlab之间转换r?

1 个答案:

答案 0 :(得分:2)

C函数cyclic需要float s的数组,但mexFunction传递double*。在不更改cyclic.c的情况下,您有两种选择:

  • 在MATLAB中将数据转换为single并获得float* mxGetData

    mexFunction

    float *a = (float*) mxGetData(prhs[0]);
    

    在MATLAB中:

    mexFunction(single(a),...)
    
  • 转换(复制,而非投射!)mexFunction中的数据。

    mexFunction中,分配新的float数组,并将双输入数组(mxGetPr(prhs[0]))中的每个元素复制到临时float数组中。

    在MATLAB中使用普通mexFunction数组调用double

做前者可能更容易。

在任何情况下你都不应该简单地使用指针,而不是你打算这样做。


此外,标量alphabetan需要作为标量从prhs读取,并作为标量传递给cyclic。在mexFunction中,使用:

float alpha = (float) mxGetScalar(prhs[...]);
float beta = (float) mxGetScalar(prhs[...]);
unsigned long n = (unsigned long) mxGetScalar(prhs[...]);

您已完全忘记c中的rmexFunction