5

I want to use Brents method as present in the Numerical Recepies Book to minimize a function. The signature of the minimzation routine essentially looks like this:

float brent(float (*f)(float), float *xmin, "other parameters not relevant to question")

As you can guess brent returns the minimum value of f and stores its argument in xmin. However, the exact form of the function I want to minimize depends on additional parameters. Say

float minimize_me(float x, float a, float b)

Once I decided on the values of a and b I want to minimize it with respect to x.

I could simply add additional arguments to all functions called, all the way down to brent, thus changing its signature to

float brent(float (*f)(float,float,float),float a ,float b , float *xmin, ...)

and consequently call (*f)(x,a,b) inside brent every time. This, however, seems not really elegant to me since I would now have to pass not only the pointer to minimize_me, but also two additional parameters down a whole chain of functions.

I suspect there could be a more elegant solution, like creating a pointer to a version of the function with a and b as fixed values.

Even if it is a really obscure solution, please don't keep it from me, since I feel it could improve my overall understanding of the language.

7
  • maybe you're looking for this? stackoverflow.com/questions/7308449/… Commented Feb 16, 2018 at 13:40
  • 1
    you might consider creating a struct with your parameters and pass its pointer to the function Commented Feb 16, 2018 at 13:40
  • @Nefrin something like typedef struct { float a; float b; float (*f)(double,double,double) } f_ab;? Am I getting this right? I am not that used to c yet. Commented Feb 16, 2018 at 13:49
  • 1
    yes @cmmnn, you can then create an instance with f_ab myAB set its values and pass its pointer into a function(void* param) with function(&myAB) and then cast it back to the f_ab type. This method alows passing structs with arbitrary content to a function with a single parameter Commented Feb 16, 2018 at 14:00
  • ok I´ll consolidate this in an answer Commented Feb 16, 2018 at 14:03

3 Answers 3

6

A viable way of achieving this is to use a struct to store all the values and pass a pointer to that to the function.

struct parameters{
    int valueA;
    int valueB;
};

int function(void* params){
    parameters* data = (parameters*) params;
    return data->valueA + data->valueB; // just an example
}

int main(){
    parameters myData;
    myData.valueA = 4;
    myData.valueB = 2;
    function(&myData);
    return 0;
}
Sign up to request clarification or add additional context in comments.

5 Comments

Nice answer +1...one small thing I want to ask you..that casting is mandatory? Just asking.
void* params is not type safe. It would be better to use argument type struct parameters * params.
yes, casting is mandatory. otherwise the compiler does not know how big the structure is and what values it contains. (although you could do the pointer arithmetic yourself)
Also, small nitpick: (parameters*) wont compile, because only type struct parameters exists. And cast is not even necessary as void* can be implicitly converted to any other object pointer type. Compiler doesn't need to know the size of pointed structure.
The idea of using a pointer to struct, I have found, is so useful in so many ways, but sadly under utilized. Nice answer!
5

What you need is currying, say for example:

given a function of three variables f(x,y,z) and two values a and b, construct the function g of one variable such that g(z)=f(a,b,z).

Alas C language is not able to let you currying. Such a construction is available to functional languages only and C is not one. This doesn't mean that you really can't do it, but there is no given construction for it in the language. So you need to reconstruct the mechanism by yourself. See Currying/binding with ISO C99 or Is there a way to do currying in C? for examples.

4 Comments

Jean nice answer(+1) but would you mind in single line explaining currying...many will be too lazy to open link from answer. (Or manybe it is not that common a topic).
I've had to do such things in C, but never knew such well developed and formalized thoughts existed, or were even named.
@ryyker well CS is...a science. So there exists a lot of theorems and alike in the field.
@Jean-BaptisteYunès - Lol, yes, I suppose so. Being one not formally educated in that field, I fear I have missed out on some very cool stuff. However, that fact also means I have a great appreciation for said cool stuff when I run into it here. :)
1

GCC's local functions extension is a pure joy to use (use -std=gnu11):

float brent(float (*f)(float), float *xmin);

float minimize_me(float x, float a, float b);

int main() {
   ...
   float min_me_local(float x) { return minimize_me(x, 1, 2); }
   brent(min_me_local, xmin);
   ...
}

I wish it was standard, but it isn't. So prefer answer from @Nefrin when aiming at portability.

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.