On Jul 6, 3:55 am, Protoman <Protoman2...@gmail.comwrote:

Is this an efficient way to integrate an explicit function of x from a

to b:

Are you talking about the algorithm, or the C++ aspects? (I

rather doubt that the algorithm even gives the correct results

all the time. I'm not enough of an expert in numeric processing

to suggest something better, but I'd definitly ask about it in a

group specialized in numeric processing to be sure.)

#include <iostream>

using namespace std;

class Integrate

{

public:

Integrate(long double (*f)(long double& x)):fn(f){}

long double operator()(long double& a, long double& b)const;

private:

long double (*fn)(long double& x);

};

Your code would be easier to read if you'd indent. (Or is the

lack of indentation the result of some "smart" processing by

your newsreader?)

Two C++ comments, however:

-- A better solution would be to define an interface for the

functional object, and have the user derive from that,

rather than use a pointer to function. That way, he can add

state to the function; e.g. to integrate a quadratic

equation:

class Quadratic : public UnaryFunction

{

public:

Quadratic( double a, double b, double c )

: a( a ), b( b ), c( c )

{

}

virtual double operator()( double x ) const

{

return ((a * x) + b) * x + c ;

}

private:

double a ;

double b ;

double c ;

} ;

-- Is there any reason for using a class here? Quite frankly,

it looks like nothing more than a simple function.

I'd probably write something like:

class UnaryFunction

{

public:

virtual ~UnaryFunction() {}

virtual double operator()( double x ) const = 0 ;

} ;

extern double integrate(

UnaryFunction const& f,

double start,

double end ) ;

long double square(long double& x);

Given the above:

class Squared : public UnaryFunction

{

public:

virtual double operator()( double x ) const

{

return x * x ;

}

} ;

int main()

{

long double a,b;

cout << "Enter a lower and upper bound: ";

cin >a >b;

Integrate integrate(square);

cout << "The integral of x^2 from " << a << " to " << b << " is " <<

integrate(a,b);

return 0;

}

long double Integrate::operator()(long double& a, long double& b)

const

{

long double sum=0.0;

// Evaluate integral{a,b} f(x) dx

for (long long n=0;n<=1000000000;n++)

{

long double x = (n/1000000000.0)*(b-a)+a;

sum +=(*fn)(x)*(b-a)/1000000001;

Here's where I have my doubts. I suspect that integrating

something like 1/x, starting with a very small value, could

introduce significant errors. (The function will also fail if

you ask the integral of 1/x over 0.0 to 1.1, which is, IMHO,

something perfectly reasonable to ask.)

}

return sum;

}

long double square(long double& x)

{

return (x*x);

}

Is there a way to do this at compile-time w/ template

metaprogramming?

You mean generating a separate function for each invocation of

integrate, to avoid the indirect or virtual function call (and

possibly inline the function, with simple functions like

square). Easy. For my functional version, just replace the

virtual base class with a template type argument:

template< typename Func >

double

integrate(

Func f,

double start,

double end )

{

// ...

}

This results in duck typing---you don't need to derive, or use

virtual functions; all you need is for the expression

"f(double)" to be legal, and evaluate to a double. (If it looks

like a duck...) You can even use a pointer to a function (but

then you will still have the indirect call). If you do this,

and drop the derivation and the virtual in Squared, above, the

compiler will probably generate the function inline. In this

case, at least on some architectures, the speed improvement

could be notable. (In more complicated cases, of course, it

could be minimal.

What about parameterizing it w/ templates?

If you use a function, rather than a class, the compiler will

automatically do type deduction for you. The templated

function, above, is used exactly like the non-templated one,

except that the constraints on the functional object are

loosened. On the other hand, it's a lot less flexible: you

can't, for example, create an array of pointers to different

types of functional objects, and iterate through it, calling

integrate in the loop. For most applications, I'd say that

giving up the flexibility (and the strict typing---duck typing

may require less typing, but it is a lot more error prone than

explicit typing) was a bad trade-off, especially as nothing says

that indirect calls are that expensive. (A quick check on my

Linux box---an Intel based PC---showed hardly any difference in

time between the templated version and the one using virtual

functions.)

You probably can't template the range parameters, since non type

template arguments can't be floating point. And it probably

wouldn't be acceptable if you could, since the calling syntax

would become:

integrate< 0.0, 1.0 >( Squared() ) ;

and the arguments would have to be constants.

--

James Kanze (GABI Software) email:ja*********@gmail.com

Conseils en informatique orientée objet/

Beratung in objektorientierter Datenverarbeitung

9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34