468,457 Members | 1,581 Online

Easy question about redefining a function

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

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

Jul 6 '06 #1
6 2029
Martin Bootsma <ma***********@gmail.comwrote:
>
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);

--
Rouben Rostamian
Jul 6 '06 #2
Martin Bootsma wrote:
I have a C question, which looks very easy, but no one here seems to

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);
--
==============
Not a pedant
==============
Jul 6 '06 #3
"Martin Bootsma" <ma***********@gmail.comwrote in message
>I have a C question, which looks very easy, but no one here seems to

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
Jul 6 '06 #4
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.

Jul 6 '06 #5
Martin Bootsma wrote:
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);
...

--
Eric Sosman
es*****@acm-dot-org.invalid
Jul 6 '06 #6
Martin Bootsma <ma***********@gmail.comwrote:
>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.

--
Rouben Rostamian
Jul 6 '06 #7