how to do this?

F

Fan Zhang

Hi,

I am working on a program which can do numerical evaluations for
integrations. The program I have is like this,

double foo(p1, p2)
double p1, p2;
{
double kk,step;
int ii;
step_sz=(p2-p1)/100.;
kk=0.;
for (ii=0;ii<100;ii++)
kk+=sin(p1+ii*step_sz)*step_sz;
return (kk);
}

This program used the basic Newton method. My question is here in my program
foo, I can only calculate the integrations for a sine function. If I want to
do an integration for a cosine function, I need to rewrite another function
foo1 with cosine being inserted in. I am sure there is a neat way to do this
without writing another function. But I do not have an answer after thinking
about it for a while. Could anybody please let me know how it is achieved?
Thanks a lot.

Regards,
Fan
 
E

Eric Sosman

Fan said:
Hi,

I am working on a program which can do numerical evaluations for
integrations. The program I have is like this,

double foo(p1, p2)
double p1, p2;

Write `double foo(double p1, double p2)' in all
new code. The old form you are using is retained for
backward compatibility with pre-ANSI C, but is
inferior to the newer style.
{
double kk,step;
int ii;
step_sz=(p2-p1)/100.;
kk=0.;
for (ii=0;ii<100;ii++)
kk+=sin(p1+ii*step_sz)*step_sz;
return (kk);
}

This program used the basic Newton method. My question is here in my program
foo, I can only calculate the integrations for a sine function. If I want to
do an integration for a cosine function, I need to rewrite another function
foo1 with cosine being inserted in. I am sure there is a neat way to do this
without writing another function. But I do not have an answer after thinking
about it for a while. Could anybody please let me know how it is achieved?
Thanks a lot.

Rewrite foo() to accept a pointer to the function
that calculates the integrand's values:

double newfoo(double p1, double p2,
double (*func)(double)) {
...
kk += func(...);
...
}

.... and call it like this:

y1 = newfoo(0.0, 3.14, sin);
y2 = newfoo(-3.14, 0.0, cos);
y3 = newfoo(42.0, 43.0, sqrt);
 
F

Fan Zhang

Eric,

Thanks! It worked.

I have a further question if you do not mind. In the new foo, which is

double newfoo(double p1, double p2,
double (*func)(double)) {
...
kk += func(...);
...
}

func can only have a certain number of parameters ( in this case, 1). The
program I am working on needs to call different functions with different
number of parameters. I suppose by calling an array instead of individual
parameters this problem can be solved. But again it does not seem to be the
best way. Is there any better way for this? Thanks!

Fan
 
F

Fred L. Kleinschmidt

Fan said:
Hi,

I am working on a program which can do numerical evaluations for
integrations. The program I have is like this,

double foo(p1, p2)
double p1, p2;
{
double kk,step;
int ii;
step_sz=(p2-p1)/100.;
kk=0.;
for (ii=0;ii<100;ii++)
kk+=sin(p1+ii*step_sz)*step_sz;
return (kk);
}

This program used the basic Newton method. My question is here in my program
foo, I can only calculate the integrations for a sine function. If I want to
do an integration for a cosine function, I need to rewrite another function
foo1 with cosine being inserted in. I am sure there is a neat way to do this
without writing another function. But I do not have an answer after thinking
about it for a while. Could anybody please let me know how it is achieved?
Thanks a lot.

Regards,
Fan

One way is to pass the function as one of the arguments. Then you could
use the same integrator for any function (as long as it passes range and
integrability requirements).
 
A

Arthur J. O'Dwyer

double newfoo(double p1, double p2,
double (*func)(double)) {
...
kk += func(...);
...
}

func can only have a certain number of parameters ( in this case, 1). The
program I am working on needs to call different functions with different
number of parameters. I suppose by calling an array instead of individual
parameters this problem can be solved. But again it does not seem to be the
best way. Is there any better way for this? Thanks!

First, do not top-post. Google "top-posting" or "netiquette" to find out
what that means.

As for your question: Not in C. The way you have it at the moment is
just about the limit of C's built-in support for this sort of thing. You
can always do something like this: [COMPLETELY UNTESTED CODE]

/*
Old routine for numerical integration: function of one variable
*/
double numint(double a, double b, double (*f)(double)) {
int i, n=42;
double sum = 0.0;
for (i=0; i < n; ++i)
sum += f(b*i + a*(n-i));
return (f(b)+2*sum-f(a))/(2*n);
}

/*
New routine for numerical integration: function of one, two,
or three variables, although we integrate only over the last
of them. Called as |numint(0, 1, 2, x_times_y, 3)| to compute
the integral of $f(x) = 3*x$ for $x=0$ to $1$. The argument
|2| specifies the number of |double| parameters expected by |f|.
*/
double numint(double a, double b, int numargs, double (*fp)(), ...) {
int i, n=42;
double sum = 0.0;
double arg1, arg2;
va_list ap;

/* Retrieve extra (constant) arguments to |f| */
va_start(ap, fp);
if (numargs > 2) arg1 = va_arg(ap, double);
if (numargs > 3) arg2 = va_arg(ap, double);

/* Perform the integration, as in the old version */
switch (numargs) {
case 1: {
double (*f)(double) = fp;
for (i=0; i < n; ++i)
sum += f(b*i + a*(n-i));
sum = f(b) + 2*sum - f(a);
break;
}
case 2: {
double (*f)(double, double) = fp;
for (i=0; i < n; ++i)
sum += f(arg1, b*i + a*(n-i));
sum = f(arg1, b) + 2*sum - f(arg1, a);
break;
}
case 3: {
double (*f)(double, double, double) = fp;
for (i=0; i < n; ++i)
sum += f(arg1, arg2, b*i + a*(n-i));
sum = f(arg1, arg2, b) + 2*sum - f(arg1, arg2, a);
break;
}
}
return sum/(2*n);
}


But that's not a very useful or elegant thing to do in C code. If you
really want to do a lot of things involving what are called "higher-order
functions," I suggest you investigate "functional programming" languages
such as OCaml, Scheme, and Haskell (all of which are of course off-topic
in c.l.c, but have their own newsgroups, including c.l.functional).

HTH,
-Arthur
 
H

Herbert Rosenau

Please stop top posting!
Eric,

Thanks! It worked.

I have a further question if you do not mind. In the new foo, which is

double newfoo(double p1, double p2,
double (*func)(double)) {
...
kk += func(...);
...
}

func can only have a certain number of parameters ( in this case, 1). The
program I am working on needs to call different functions with different
number of parameters. I suppose by calling an array instead of individual
parameters this problem can be solved. But again it does not seem to be the
best way. Is there any better way for this? Thanks!

Write wrappers to the fuctions using less parameters than the one with
the most number of parameters.
There is no problem to give a fuction more parameters as it will
access - but the parameters have always to match in number and type.

You may change the interface to newfoo agin e.g.:
double newfoo(double p1, double p2, unsigned int index) {
...
kk += wrapit(index, double p1, double p2, <more parameters one of
the funcs may need>);
...
}

double wrapit(int index, <parameter list containing any parameter
needed for any function>) {

switch (index) {
case SINUS: return sin(p1);
case COS: return cos(p1);
case xx1: return xx1(p1, p5, p4, p2);
case xx2: return xx2(p3, p4);
::::
}
}

Surely, you can give 0, 0.0 or so for parameters not used in a
partikular case.
 

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

No members online now.

Forum statistics

Threads
474,154
Messages
2,570,870
Members
47,400
Latest member
FloridaFvt

Latest Threads

Top