0

I am working on C implementations of calculus operations (such as derivatives, integrals, etc...). As an example, here's the template definition of my derivative function:

double derivative(double (*f)(double), double x);

Let's say I want to compute the derivative of exp at 1, the call would then be: derivative(exp, 1);

Pretty basic stuff. Now my question is, how would I go about (if it is even possible) to pass a composition to my derivative function? I tried passing exp(cos) which got me

error: passing 'double (double)' to parameter of incompatible type 'double'.

How would I do it? Is it even possible?

4
  • I don't understand the question. How does it make sense to pass the cos function to the exp function? Can you give an example of the actual equations you want this to solve? Commented Jul 2, 2021 at 8:54
  • @Lundin what I would like to be able to do is to compute the derivative of any composition (exp(cos(x)) was just an example, ln(sqrt(x)) is another) Commented Jul 2, 2021 at 9:00
  • 1
    In that case, the correct solution is to call the functions in sequence. It probably doesn't make much sense to implement such equations using generic programming. Commented Jul 2, 2021 at 9:07
  • One might be forgiven to think C is the wrong language here? What is feasible is not always what is possible. Commented Jul 2, 2021 at 13:46

3 Answers 3

2

I think you're asking for this:

double composition(double x) {
   return exp(cos(x));
}

derivative(composition, 1);

Many languages allow you to do something like the following, but C doesn't have anon functions:

derivative(x => exp(cos(x)), 1);
Sign up to request clarification or add additional context in comments.

Comments

1

If you want some sort of run-time control over the composition, you could write a function that evaluates an array of function pointers as a composition:

// calls functions in reverse order
double compose(size_t n, double (* const fc[])(double), double x)
{
    while (n--)
    {
        x = fc[n](x);
    }
    return x;
}

This could be called from another version of your derivative function:

double derivative_composed(size_t n, double (* const fc[])(double), double x)
{
    // Example implementation for illustrative purpose only.
    double fx, fxh, h;
    h = x / 1e10;
    if (h == 0)
    {
        h = 1e-10;
    }
    fx = compose(n, fc, x);
    fxh = compose(n, fc, x + h);
    return (fxh - fx) / h;
}

To avoid repeated code, your original derivative function could be changed to be a wrapper that calls derivative_composed with a single function:

double derivative(double (* const f), double x)
{
    return derivative_composed(1, &f, x);
}

Example usage:

int main(void)
{
    double (* const fc[2])(double) = { exp, cos };
    double x = 1.0;
    double xprime = derivative_composed(2, fc, x);
    printf("x = %f, xprime = %f\n", x, xprime);
}

Output:

x = 1.000000, xprime = -1.444407

1 Comment

Yes, I guess this is the only "practical" way to go about doing what I intend to. Thanks for the answer and code sample!
1

C does not have any operation for function composition. To compute the derivative of exp∘cos, you can define a function expcos:

double expcos(double x) 
{
    return exp(cos(x));
}

and take the derivative of that.

For a more general solution, you could modify your derivative routine to take both a function pointer and a const void * to forward to the function. The function would take the const void * as a parameter, convert it to a pointer to a const structure of a type particular to that function, and take data from that structure. Then function composition can be implemented with a compose function that uses a structure containing two function pointers. However, it would mean you would need to use proxy routines for ordinary functions like exp and cos that accept but ignore the const void *.

Comments

Your Answer

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.