Kai-Uwe Bux
11/16/2008 12:01:00 AM
James Kanze wrote:
> On Nov 15, 11:48 am, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
>> James Kanze wrote:
>> > On Nov 15, 10:26 am, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
>> >> pauldepst...@att.net wrote:
>> >> > Let double NR( double x, double(*)(const double&) f ) be the
>> >> > signature of a Newton-Raphson function NR.
>
>> >> > Here, f is a function which returns a double and accepts
>> >> > a const double&. The aim of the game is to find a
>> >> > zero of this function f (the point at which f crosses the
>> >> > x-axis). This zero-of-f which solves our problem is the
>> >> > double which NR returns. It remains to explain what the
>> >> > "double x" represents. This is the starting-guess that
>> >> > is required in Newton-Raphson implementations.
>
>> >> > In my case, I have the following amended Newton-Raphson
>> >> > situation. I have a function of the form
>
>> >> > double MyFunc(double x1, double x2, double x3, double x4, double x5)
>
>> >> > I want to solve the following problem: Fix x1, x2, x3,
>> >> > and x4. Then use Newton Raphson to return the double y
>> >> > such that MyFunc(x1, x2, x3, x4, y) = 0.
>
>> >> > I was unable to find a way of using the ready-made
>> >> > function NR because it assumes f accepts 1 double and
>> >> > returns 1 double, whereas My Func accepts 5 doubles and
>> >> > returns 1 double.
>
>> >> > My very-inelegant solution was to copy-paste the NR code
>> >> > and adapt it so that the pointer-to-function parameter
>> >> > was of the type I needed.
>
>> >> > Is there a more elegant approach that calls on the NR
>> >> > function already present?
>
>> >> I would change NR into a template:
>
>> >> template < typename Float, typename Func >
>> >> Float find_zero ( Float initial_guess, Func f );
>
>> >> Then, you could use bind() from c++0x or Boost to fix the
>> >> first four arguments and pass the resulting function object
>> >> into the template.
>
>> > This is a very elegant solution for a few special cases, but
>> > it results in an infection template; if the call to this
>> > function is in a function which receives the callback
>> > function as an argument, that function must be a template as
>> > well.
>
>> Huh? I admit that this sentence has too many "this" and "that"
>> for me to get references straight. So, I do not really
>> understand what you mean. Anyway, I also do not see any reason
>> why this template could not be called from ordinary functions:
>
> The problem is that the fact that it is a template, and is not
> resolved dynamically, propagates. If the ordinary function
> calls it with a known callback, fine; the propagation stops
> there. But if the ordinary function calls it with a functor
> that is passed in, then if templates are used, the ordinary
> function has to be a template too. And so on; imagine what
> would happen if iostream used templates, rather than virtual
> functions, in streambuf.
You keep using pronouns and terms like "ordinary function" whose reference
is not clear to me. Maybe, I am just dense.
So for concreteness, here is a simple template implementation of find_zero
using the Newton method:
template < typename Float, typename Func >
Float find_zero ( Func f,
Float initial_guess,
Float eps = std::numeric_limits<Float>::epsilon() * 1000,
Float h = std::numeric_limits<Float>::epsilon() * 1000,
unsigned int iteration_limit = 50 ) {
Float x = initial_guess;
for ( unsigned int n = 0; n < iteration_limit; ++n ) {
Float y = f(x);
if ( std::abs(y) < eps ) {
return (x);
}
x = x - y * h / ( f(x+h/2) - f(x-h/2) );
}
throw( std::invalid_argument( "iteration limit exceeded" ) );
}
I fail to see any problem with that. Clearly, there is no requirement that
the call back function f has to be a template or that this function can
only be called from templates. If one uses the signature
template < typename Float, typename Func >
Float find_zero ( Func const & f,
Float initial_guess,
Float eps = std::numeric_limits<Float>::epsilon() * 1000,
Float h = std::numeric_limits<Float>::epsilon() * 1000,
unsigned int iteration_limit = 50 );
one can even support the inheritance based solution you suggested
elsethread.
If you could provide code that illustrates the propagation of templates with
this example, it would be highly appreciated.
>> template < typename Float, typename Func >
>> Float find_zero ( Float initial_guess, Func f ) {
>> return ( 1 );
>> }
>
>> double caller ( double x, double(*f)(double) ) {
>> return ( find_zero( x, f ) );
>> }
>
> In this case, I fail to see what you've gained with respect to
> the initial problem.
Nothing: the code is just meant to illustrate why I don't see that something
propagates. That why the function is called "caller". Clearly, I am still
missing your point.
>> double id ( double x ) {
>> return (x);
>> }
>
>> #include <iostream>
>> #include <ostream>
>
>> int main ( void ) {
>> std::cout << caller( 1.0, &id ) << '\n';
>> }
>
>> (BTW: a Google search for "infection template" only yield
>> medical stuff.)
>
> Yes. I'm not really sure what the appropriate word should be.
> The closest analogy I can think of is the GNU license, but of
> course, templates aren't that infectious. The fact remains that
> any time you implement genericity with a template, it means that
> any client code which wants to maintain that genericity neads to
> be a template as well.
Here the key phrase is "wants to maintain that genericity". There is no
reason for client code to always be like that. All algorithms is the
standard library are templates and they are used in non-templated code. I
do not see the infectious trait you mention.
> Anytime you have a real choice, you
> should prefer inheritance with virtual functions to templates.
I disagree. In my codebase, that would be utterly inappropriate. More to the
point: finding roots of functions clearly seems like a task for a template
and forcing clients to inherit from some call back just to fit the
interface is clearly wrong.
> (Of course, most of the time you don't have a real choice;
> templates are designed to solve a different set of problems than
> virtual functions.)
Agreed.
Best
Kai-Uwe Bux