1

I am trying to calculate the Jacobian matrix (numerical, at a given point) of a given equation. Now, I don't know the dimension of the equation beforehand, so I can't just do something like

static double f(double x1, x2)
{
 return x1 * x1 - 2 * x1 * x2;
}

so instead, I am getting the input values as an array like so


static double f(double xArray[]) 
{
 return xArray[0] * xArray[0] - 2 * xArray[1] * xArray[0];
}
void jacobian(double xArray[], double jacob_matrix, size_t size,
 double f(double xArray[], size_t)) 
{
 // calculations
}

However, when I try to call the function from main like

int main(void)
{
 double x_input[4] = {1., 1., 3., 4.};
 double jacob_matrix[4]; 
 
 jacobian(x_input, jacob_matrix, 4, f(x_input, 4));
 return 0;
}

I get incompatible type for argument 4 of 'jacobian' I imagine this has to do with my array being casted into a pointer, but I can't figure out how to fix this.

anastaciu
24.1k7 gold badges37 silver badges62 bronze badges
asked Jan 3, 2022 at 10:07
3
  • Learn about function pointers and how to use them, that's what you probably want to do. Commented Jan 3, 2022 at 10:09
  • please add the definition of f function Commented Jan 3, 2022 at 10:13
  • @kiner_shah Apparently that's what I was missing. @tstanisl I must've added in the second snippet with static double f... Commented Jan 3, 2022 at 10:18

2 Answers 2

2

You need to pass the function pointer to f, not the result of calling f. Try:

jacobian(x_input, jacob_matrix, 4, f);
answered Jan 3, 2022 at 10:11
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks. That seems to work. I only have to change how I call jacobian, not its arguments I suppose? Does f choose its input array to be xArray because of ` void jacobian(double xArray[], double jacob_matrix, size_t size, double f(double xArray[], size_t)) ` ?
@ofey, parameter jacob_matrix is a scalar of type double. Probably you would like to change it to double jacob_matrix[].
Ah sorry. The original code was on another computer, so I was manually typing it. In my original implementation, jacob_matrix is as you've suggested.
1

For the function signature:

void jacobian(double xArray[], double jacob_matrix, size_t size,
 double f(double xArray[], size_t)) 

For the second argument, if you're going to pass an array you need the argument to be a pointer, double* jacob_matrix or double jacob_matrix[].

For the 4th argument, the passed function arguments should match the caller signature, so in your case you are passing a function which is of type double (*)(double *), but the caller expects a function of type double (*)(double *, size_t), so one of them should be changed to match, either add a second argument to the called function, or remove the second argument of the caller function signature.

#include <stdio.h>
static double f(double xArray[]) 
{
 return xArray[0] * xArray[0] - 2 * xArray[1] * xArray[0];
}
void jacobian(double xArray[], double* jacob_matrix, size_t size,
 double f(double xArray[])) 
{ 
 printf("%f", f(xArray)); // for example
}
int main(void)
{
 double x_input[4] = {1., 1., 3., 4.};
 double jacob_matrix[4]; 
 
 jacobian(x_input, jacob_matrix, 4, f);
 return 0;
}

Note that my approach only addresses the code correctness and not the mathematical part, i.e. the jacobian calculation.

answered Jan 3, 2022 at 10:38

8 Comments

Thanks for the detailed answer! I was wondering, normally when we are passing a function as a parameter, we can do void jacob(double f(double x)) when x is of type double. In the case of pointer, can we just use the function signature as void jacobian(double xArray[], double* jacob_matrix, size_t size, double f(double* )) But I guess in this case, then f cannot match its input argument with x_input.
Using a typedef for the function type would increase readability.
@ofey, I'm not sure I understand your doubt, but x_input is passed correctly, an array passed as argument of a function will decay to a pointer to its first element, so it is correct.
@ofey as for the function argument, the passed function arguments should match the caller signature, so in your case you are passing a function which is of type double (*)(double *), but the caller expects a function of type double (*)(double *, size_t), so one of them should be changed to match, either add a second argument to the called function, or remove the second argument of the caller function signature.
@ofey, you need to do it yourself, you're only passing a function, for example void jacobian(double xArray[], double* jacob_matrix, size_t size, double f(double xArray[])) { double a[] = {5}; printf("%f", f(a)); }
|

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.