replacement for dynamic template parameter

M

Marcel Sebbao

I have a function that returns {sin(x),x,cos(x)} depending on a
parameter k that can take only 3 integer values: -1, 0, 1.
I am trying to do this with template specialization:

enum curv { negative=-1, zero=0, positive=1 };
template<curv k> double scurv(const double& x);
template<> double scurv<negative>(const double& x) { return sin(x); }
template<> double scurv<zero> (const double& x) { return x;}
template<> double scurv<positive> (const double& x) { return cos(x); }
curv guess_curv(const double& ym)
{
if (ym<0) return negative;
if (ym>0) return positive;
return zero;
}


Next, I would like to use this function in a class:


class Yfunc {

const curv k;
const double& y;

public:

inpa(const double& M, const double& Y)
: k(guess_curv(M+Y)), y(Y) {}

double ez(const double& a) const {
return scurv<k>(x) * pow(y*a, 0.6) ;
}
};


Such that I construct Yfunc once, k is determined, and I do not test
for k each time I call Yfunc::ez.
Template parameters do note allow this dynamical parameter setting .
Is there a smart way to overcome this, yet as performant as template
specialization? I was thinking of function pointer but it was not as
elegant.

Thanks.
 
D

Donovan Rebbechi

Such that I construct Yfunc once, k is determined, and I do not test
for k each time I call Yfunc::ez.
Template parameters do note allow this dynamical parameter setting .
Is there a smart way to overcome this, yet as performant as template
specialization? I was thinking of function pointer but it was not as
elegant.

Function object + subclassing. Note that however you do runtime selection, if
you are doing the selection at runtime there is inherent overhead in that (if
you use polymorphism or function pointer, you have a pointer deref) So you
don't get the same performance as you would with compile-time template
selection.

Cheers,
 
D

Donovan Rebbechi

Such that I construct Yfunc once, k is determined, and I do not test
for k each time I call Yfunc::ez.
Template parameters do note allow this dynamical parameter setting .
Is there a smart way to overcome this, yet as performant as template
specialization? I was thinking of function pointer but it was not as
elegant.

btw, depending on your usage, it may help to have a member function that
calls your function on a range, e.g. MyFunc(v.begin(),v.end(),result.begin());

Anyway, my point is that there might be a way to abstract the "making multiple
calls" in a way that allows you to perform the indirection only once per usage.

Cheers,
 
M

Martin Eisenberg

Marcel said:
I have a function that returns {sin(x),x,cos(x)} depending on a
parameter k that can take only 3 integer values: -1, 0, 1.
I am trying to do this with template specialization: [snip]
Such that I construct Yfunc once, k is determined, and I do not
test for k each time I call Yfunc::ez.

Are you sure that computing transcendentals won't overwhelm
any savings in avoiding the runtime comparison?
 
M

Marcel Sebbao

Thanks for the feedback.
I thought the compiler was generating 3 functions and will call it
appropriately only at runtime.

I finally decided on the quickest change: make the Yfunc class a
template class:


template<curv k>
class Yfunc {

const double& y;

public:

inpa(const double& Y)
: y(Y) {}

double ez(const double& a) const {
return scurv<k>(x) * pow(y*a, 0.6) ;
}
};

Then I call it within an if statement.

What is "computing transcendentals"?
 
M

Martin Eisenberg

Marcel said:
What is "computing transcendentals"?

Carrying out a process that takes a given number into an
approximation of its image under one of a certain class of
mathematical functions -- to which sine and cosine belong. This can
be quite computationally expensive, so the time the library calls
take is likely to drown out some more comparisons unless your
parameter k selects the identity map in most cases. Profile your code
with runtime comparisons to find out if sin() and cos() are hot
spots. If so, explore alternative implementations with your accuracy
requirements in mind, and if you need help with that, visit
sci.math.num-analysis. If you need help with profiling, visit
comp.programming or a group about your development environment.

http://mathworld.wolfram.com/TranscendentalFunction.html
 
S

sebbao

Well it looks like I had to get rid of the template stuff.
I did some tests, and the computation of transcendental functions is
more costly.
I adopted for pointer to function :(


static inline double identity(double x) { return x; }

class Yfunc {
const double& y;
public:

double (*Sc)(double x);

Yfunc(const double& M, const double& Y): y(Y) {
if (y+M<0) Sc = &sin;
else if (y+M>0) Sc = &cos;
else Sc = &identity;
}

double ez(const double& a) const {
return Sc(a) * pow(y*a, 0.6);
}

};
 

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,202
Messages
2,571,057
Members
47,661
Latest member
sxarexu

Latest Threads

Top