Thread: Matlab into C Function

  1. #1
    Registered User
    Join Date
    Apr 2008
    Posts
    204

    Matlab into C Function

    Hi I have written a function in matlab that I now want to convert to C. However Matlab has matrices functions where C does not. I have converted the function and I now think that the two should be doing the same thing however the C version is calculating #QNAN0 in other words the value is tending to infinity due to a /0.

    I was wondering if there is someone out there who has used both matlab and C and can tell if i have made a mistake - I cant see it

    So I have solved a problem in matlab and it works brilliantly. However my boss requires the method in C. I am doing a least squares minimization using fminsearch. I am trying to replicate the function being solved for in C (I already have the neldermead function in C)

    My matlab function to be solved is:

    Code:
    function sse=myfit(params,Input,Actual_Output)
    global c
    a=params(1);
    b=params(2);
    
    
    x = (exp(a*2*pi)-cosh(a*b*Actual_Output))/sinh(a*b*Actual_Output);
    c = -1/atanh(x);
    Fitted_Curve = (1/(a*b))*(c-asinh(sinh(c)*exp(a*Input*2*pi)));
    Error_Vector=Actual_Output-Fitted_Curve ;
    sse=sum(Error_Vector.^2);
    And this is what I am trying to replicate in C:

    Code:
    static double function(int n, double x[])
    {
    	double c[5], x_coeff[5];
        double Fitted_Curve[5];
        double Error_Vector[5];
        int i;
        double Actual_Output[5]={1.2, 2.693, 4.325, 6.131, 8.125};
      double Input[5]={1, 2, 3, 4, 5};
      double sum = 0;
    
      for (i = 0; i <= 4; i++)
      {
    
        x_coeff[i] = (exp(x[0]*2*pi)-cosh(x[0]*x[1]*Actual_Output[0]))/(sinh(x[0]*x[1]*Actual_Output[0]));
    
        c[i] = (-1)/(atanh(x_coeff[i]));
    
        Fitted_Curve[i] = (1/(x[0]*x[1]))*(c[i]-asinh(sinh(c[i])*exp(x[0]*Input[i]*2*pi)));
    
        Error_Vector[i] = Actual_Output[i]-Fitted_Curve[i];
    
     printf(" x_coeff(%d) =   %f  %f\n", i, x_coeff[i], c[i]);
        }
    
    
    
        for (i = 0; i <= 4; i++)
        {
            sum = sum + Error_Vector[i]*Error_Vector[i];
        }
    
    
        return sum;
    
    }
    I know I am not passing the function the vectors in C but declaring them everytime, but I dont think this will effect the result as the vectors are constant?
    It doesnt give the same answer (atanh(x>1) = inf) which obviously suggests they are not doing the same thing. Can anyone see where I have gone wrong?

    Thanks

  2. #2
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Matlab is smart enough to detect that you're computing 1/infinity and give a result of zero. C is not.

    Usually, rather than just trying to map matlab to C, you are better off working back to a human-readable description of the algorithm, and working out the best way to implement that. It would probably have helped to do things using the same variable names (such as a and b), but that's a quibble on clarity only (it is harder to get code right if it is not written clearly).
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  3. #3
    Registered User
    Join Date
    Apr 2008
    Posts
    204
    Ok so for clarity I have changed the parameters to a and b:
    Code:
    static double function(int n, double x[])
    {
    	double c[5], x_coeff[5];
        double Fitted_Curve[5];
        double Error_Vector[5];
        int i;
        double Actual_Output[5]={1.2, 2.693, 4.325, 6.131, 8.125};
      double Input[5]={1, 2, 3, 4, 5};
      double a, b, sum = 0;
    
    	/*double	x0, x1;
    
    	x0 = x[0];
    	x1 = x[1];
    	return (x0-2)*(x0-2) + (x1-3)*(x1-3);
    */
    a = x[0];
    b=x[1];
    
      for (i = 0; i <= 4; i++)
      {
    
        x_coeff[i] = (exp(a*2*pi)-cosh(a*b*Actual_Output[i]))/(sinh(a*b*Actual_Output[i]));
    
        c[i] = (-1)/(atanh(x_coeff[i]));
    
        Fitted_Curve[i] = (1/(a*b))*(c[i]-asinh(sinh(c[i])*exp(a*Input[i]*2*pi)));
    
        Error_Vector[i] = Actual_Output[i]-Fitted_Curve[i];
    
     printf(" x_coeff(%d) =   %f  %f\n", i, x_coeff[i], c[i]);
        }
    
    
    
        for (i = 0; i <= 4; i++)
        {
            sum = sum + Error_Vector[i]*Error_Vector[i];
        }
    
    
        return sum;
    
    }
    where it prints x_coeff and c, I have attached some of the output in the console, where x_coeff = 1, c = -0.114905.
    Matlab into C Function-console-jpg
    The human readable form is the original equation I derived. My problem is whether C is doing what I expect it to be doing:
    The vectors Input and Actual_Output, are they ok here or could this be a problem?
    By returning sum, that does not include x[0] and x[1], will they be updated by the function that called them? I am worried that they are not being updated?

    As far as I understand, the code is calculating an x_coeff, c, Fitted_Curve, Error_Vector for each value of Input and Actual Output
    then it is summing the squares of the Error_Vector variable and returning that value to the function that called it.

    But this isnt the problem, the problem is the values of x_coeff are not the same as they are in matlab, i dont think this is anything to do with the loop, I think this is a maths issue???

  4. #4
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    54 posts, and finally a post that contains usable information! I applaud you sir.

    There's nothing wrong with Input or Actual_Output.

    Nobody is updating x[0] or x[1] here in this function. If you had updated x[0] or x[1] in this function, then those changes would be seen in main (or wherever you called this function from). Matlab wasn't updating a or b as far as I could see either, so I don't know how you want x[0] or x[1] to update. The part you've written under "As far as I understand" is all correct.

    I can't test the numbers until you tell me what x[0] and x[1] are, and what you've defined pi to be.

  5. #5
    Registered User
    Join Date
    Apr 2008
    Posts
    204
    Hi tabstop: yeah I know not very good at posting am I. As confidence grows though... I have managed to get further with the function. I didnt before understand what the '/' was actually doing in matlab, I later found out t is taking the norm of the vector, so my function code has now been updated to calculate this. the good new is I am getting real numbers, the bad news is they dont match to my matlab:
    Code:
    static double function(int n, double x[])
    {
    	double c;
        double Fitted_Curve[5];
        double Error_Vector[5];
        int i;
        double Input[5]={1, 2, 3, 4, 5};
        double a, b, sum = 0;
        double Actual_Output[5]={1.2, 2.693, 4.325, 6.131, 8.125}, v1[5], v2[5], geom_inv[5], norm, norm_2, v2sum, x_coeff = 0;
    
    a = x[0];
    b=x[1];
    for (i = 0; i<=4; i++)
    {
        v1[i] = (exp(a*2*pi)-cosh(a*b*Actual_Output[i]));
        v2[i] = (sinh(a*b*Actual_Output[i]));
        //printf("%f\n", v1[i]);
    }
    for (i = 0; i<=4; i++)
    {
        v2sum=v2sum+(v2[i]*v2[i]);
    }
    norm = sqrt(v2sum);
    //printf("%f", norm);
    norm_2 = norm*norm;
    for (i = 0; i<=4; i++)
    {
        geom_inv[i] = v2[i]/norm_2;
    }
    
    for (i = 0; i<=4; i++)
    {
        x_coeff = x_coeff + v1[i]*geom_inv[i];
    
    }
    printf("a = %f, b = %f, x = %f\n",a,b, x_coeff);
    
    c = (-1)/(atanh(x_coeff));
     //printf(" c(%d)=  %f\n",  i, c);
      for (i = 0; i <= 4; i++)
      {
    
        Fitted_Curve[i] = (1/(a*b))*(c-asinh(sinh(c)*exp(a*Input[i]*2*pi)));
    
        Error_Vector[i] = Actual_Output[i]-Fitted_Curve[i];
        }
    
        for (i = 0; i <= 4; i++)
        {
            sum = sum + Error_Vector[i]*Error_Vector[i];
        }
    
    
        return sum;
    
    }
    I worked this out by writing a program in C to replicate the matlab calculation of x:

    Code:
    void main()
    {
        double Actual_Output[5]={1.2, 2.693, 4.325, 6.131, 8.125}, v1[5], v2[5], geom_inv[5], norm, norm_2, v2sum, a, b, x_coeff;
        int i;
    
    a = -1;
    b=1;
     for (i = 0; i<=4; i++)
    {
        v1[i] = (exp(a*2*pi)-cosh(a*b*Actual_Output[i]));
        v2[i] = (sinh(a*b*Actual_Output[i]));
        //printf("%f\n", v1[i]);
    }
    for (i = 0; i<=4; i++)
    {
        v2sum=v2sum+(v2[i]*v2[i]);
    }
    norm = sqrt(v2sum);
    //printf("%f", norm);
    norm_2 = norm*norm;
    for (i = 0; i<=4; i++)
    {
        geom_inv[i] = v2[i]/norm_2;
    }
    
    for (i = 0; i<=4; i++)
    {
        x_coeff = x_coeff + v1[i]*geom_inv[i];
    }
    printf("%f", x_coeff);
    }
    I then just added that back in to calculate x_coeff.
    When the program is run by itself it calculates the same value as the matlab code for x_coeff, however run in the loop and it changes the value of x_coeff where matlab keeps it constant.
    The equivelent matlab is:
    Code:
    Data=[1.2 2.693 4.325 6.131 8.125] 
    a=1;b=1; 
    v1=(exp(a*2*pi)-cosh(a*b*Data)); 
    v2=sinh(a*b*Data); 
    x = (exp(a*2*pi)-cosh(a*b*Data))/sinh(a*b*Data) 
    x1=v1*(v2/norm(v2)^2)' %Inverse Vector using Geometric Multiplication
    i.e in the above x and x1 are the same, therefore i used the basis of x1 to calculate it in C.
    I started x[0] on -1, and x[1] on 1. pi is defined as 3.1415 at the moment.

  6. #6
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    It's a common thing for people to do: you've been working on the problem so long that you forget that we haven't. You'll do fine.

    I don't see where you start your x_coeff off with any sort of initial value. You're adding things together to get this x_coeff, so you should probably set x_coeff to 0 at the beginning of the loop.

  7. #7
    Registered User
    Join Date
    Apr 2008
    Posts
    204
    You saint. That was it, if you look in the top block of code in my last post x_coeff is set to 0, however v2sum was not.
    Thank you!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Matlab Help
    By anirban in forum Tech Board
    Replies: 1
    Last Post: 09-02-2010, 05:00 AM
  2. Array equivalent to MatLab's 'find' function
    By magda3227 in forum C Programming
    Replies: 2
    Last Post: 06-16-2008, 02:54 PM
  3. C++ to matlab
    By loga in forum C++ Programming
    Replies: 1
    Last Post: 02-10-2008, 01:33 AM
  4. Matlab vs. R
    By ch147 in forum A Brief History of Cprogramming.com
    Replies: 18
    Last Post: 11-14-2007, 11:57 AM
  5. MATLAB Help
    By Lrnr in forum Tech Board
    Replies: 2
    Last Post: 02-23-2003, 10:29 AM

Tags for this Thread