Easy question about redefining a function

M

Martin Bootsma

I have a C question, which looks very easy, but no one here seems to
know an easy answer.

I have a function "powell" (from Numerical Recipes) which takes an
argument of the type

"double (*f)(float[])"

But I want to be able to pass a

"double (*f)(float[], double)"

instead, where minimization is with respect to the the first argument
and
the second argument is a parameter.

Below is a very easy version of the problem.

// Problem: Minimize function with additional parameters

// function you want to minimize, example below is trivial
// and 1 dimensional

double g(float x[],double a)
{ return (x[1]+a)*(x[1]+a); }

// so minimization should result in x[1]=-a.


int main (void)
{
//define other parameters required for the function powell
int n=1;
float *p,**xi;
p=vector(1,n);
p[1]=0.2;
xi=matrix(1,n,1,n);
xi[1][1]=1;
float ftol=0.000001;
int iter=0;
float fret;

double a=(double) rand();

//How to pass the parameter a into the minimization function powell.
//While the parameter a is defined during the running time.
//i.e., one likes to enter g(.,a) in te function

powell(p,xi,n,ftol,&iter,&fret, );
//where the last argument should be a function of the required form

}

Any help is appreciated.

Martin
 
R

Rouben Rostamian

I have a function "powell" (from Numerical Recipes) which takes an
argument of the type

"double (*f)(float[])"

But I want to be able to pass a

"double (*f)(float[], double)"
.... for example:
double g(float x[],double a)
{ return (x[1]+a)*(x[1]+a); }

Change powell() to make it accept a parameter which it
will pass to the function f.

Therefore, let:

typedef double (*ObjFunc)(float[], double *);

and change powell's declaration to:

int powell(whaterver, ObjFunc f, double param);

Then within the definition of powell(), change all calls to
f(x) to f(x, param).

Now you can call powell() as:

powell(whatever, g, 3.14);
 
P

pemo

Martin said:
I have a C question, which looks very easy, but no one here seems to
know an easy answer.

I have a function "powell" (from Numerical Recipes) which takes an
argument of the type

"double (*f)(float[])"

But I want to be able to pass a

"double (*f)(float[], double)"

instead, where minimization is with respect to the the first argument
and
the second argument is a parameter.

Below is a very easy version of the problem.

// Problem: Minimize function with additional parameters

// function you want to minimize, example below is trivial
// and 1 dimensional

double g(float x[],double a)
{ return (x[1]+a)*(x[1]+a); }

// so minimization should result in x[1]=-a.


int main (void)
{
//define other parameters required for the function powell
int n=1;
float *p,**xi;
p=vector(1,n);
p[1]=0.2;
xi=matrix(1,n,1,n);
xi[1][1]=1;
float ftol=0.000001;
int iter=0;
float fret;

double a=(double) rand();

//How to pass the parameter a into the minimization function powell.
//While the parameter a is defined during the running time.
//i.e., one likes to enter g(.,a) in te function

powell(p,xi,n,ftol,&iter,&fret, );
//where the last argument should be a function of the required form

}


Do you mean something like this ...

float lastArg(float fa[], double d)
{
...
}

float (*func)(float [], double) = lastArg;

powell(p, xi, n, ftol, iter, fret, func);
 
A

Alex Fraser

Martin Bootsma said:
I have a C question, which looks very easy, but no one here seems to
know an easy answer.

I have a function "powell" (from Numerical Recipes) which takes an
argument of the type

"double (*f)(float[])"

But I want to be able to pass a

"double (*f)(float[], double)"

instead, where minimization is with respect to the the first argument
and the second argument is a parameter.

You can't do that without modifying the "powell" function to accept the
value of the extra parameter, to have the correct function pointer type
parameter, and to pass the extra parameter to the function.

A common, generic solution for functions that have a function pointer
parameter is for them to have an additional parameter of type void *, which
is passed to the callback function (often as the first argument). For
example:

void powell(/* ..., */ double (*f)(void *, float *), void *vp) {
/* ... */
f(vp, pointer_to_float);
/* ... */
}

double g(void *vp, float *x) {
double *pa = vp;
double a = *pa;
return (x[1] + a) * (x[1] + a);
}

In the calling code:
double a = some_value;
powell(/* ..., */ g, &a);

Without modifying the "powell" function, your only option is to use a
global, eg:

double a;

double g(float *x) {
return (x[1] + a) * (x[1] + a);
}

Then do:

a = some_value;
powell(/* ..., */ g);

Alex
 
M

Martin Bootsma

Thanks all, I was hoping there was some kind of function that would
produce the equivalent of the mathematical notation

f(.)=g(.,a)

so that I could call powell with the function f in it, but according to
the reactions, there is no clever way to arrange this. I am going to
change the powell code to make the minimization possible.
 
E

Eric Sosman

Martin said:
Thanks all, I was hoping there was some kind of function that would
produce the equivalent of the mathematical notation

f(.)=g(.,a)

so that I could call powell with the function f in it, but according to
the reactions, there is no clever way to arrange this. I am going to
change the powell code to make the minimization possible.

One other possibility, not especially attractive but
perhaps expedient, is to pass the "parameter" to f() by
storing its value in a static variable:

static double fake_param;

double f(float vector[]) {
return vector[0] + vector[1] * fake_param;
}

...
fake_param = a;
powell (f);
...
 
R

Rouben Rostamian

Thanks all, I was hoping there was some kind of function that would
produce the equivalent of the mathematical notation

f(.)=g(.,a)

so that I could call powell with the function f in it, but according to
the reactions, there is no clever way to arrange this. I am going to
change the powell code to make the minimization possible.

The equivalent of setting f(.)=g(.,a) is a central feature
of functional programming languages such as Lisp, where the
process of creating the function f out g is known as "currying".

Unfortunately currying is not possible in the current version
of C where functions do not have first class object status.
Let's hope that in some future version of C this will become
possible.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top