[Proto] Reducing domain check in operator
Actually, Proto defiens operators that STATIC_ASSERT when the left and right operand domain types are no the same using is_same. How could I have those check be looser than is_same ? Should I just overload boost::is_same for my domain type and perform a proper test here or is there a way to incorporate this into Proto ? Thanks in advance
Joel Falcou wrote:
Actually, Proto defiens operators that STATIC_ASSERT when the left and right operand domain types are no the same using is_same. How could I have those check be looser than is_same ? Should I just overload boost::is_same for my domain type and perform a proper test here or is there a way to incorporate this into Proto ?
Could you tell me a bit more about your usage scenario? This is certainly an area in which Proto can improve, and I want to understand your requirements. -- Eric Niebler BoostPro Computing http://www.boostpro.com
Eric Niebler a écrit :
Could you tell me a bit more about your usage scenario? This is certainly an area in which Proto can improve, and I want to understand your requirements. I'm still working with this vec<T> grammar.
Basically I have template domain and template grammar and I want to have element of two different grammar type instance to be usable by the other for some operator/function. For example, I have a SIMD float entity : vec<float> x; Normally, the grammar that dictates this entity behvaior is tempalte<class SIMDTypeInfo> struct grammar : or_< terminal< simd_data<SIMDTypeInfo> > , arithmetic_values , nary_expr< _, narg< grammar<SIMDTypeInfo> >
{};
(or something related)
This grmmar ensure that I can write things like :
vec<float>+vec<float>
but i can't do :
vec<float>+vec<char>
For most functions and operator it's sufficent.
But there is a few SIMD operator like for example exponent that can take
any vec<T> and return a vec
Joel Falcou wrote:
But there is a few SIMD operator like for example exponent that can take any vec<T> and return a vec
. Currently the operators/functions use the underlying simd expression info to determine their domain, thus leading to problem like :
exponent(vec<float>) + vec
failing to compile cause the domain are not the same.
Now that I think of it, there is maybe a more elegant solution than hacking the domain check but i'M a bit short of ideas atm.
Strange, you shouldn't be seeing this error in this case. For
operator(), Proto doesn't enforce domains to match -- the resulting
expression assumes the domain of the lhs. Consider the following:
#include
Eric Niebler a écrit :
_1 and _2 are in different domains, but _1(_2) is allowed and is in the domain of _1. That's why the expression "_1(_2) + _1" is permitted, but "_1(_2) + _2" is not.
You might have to post your code for us to get to the bottom of this. Could it come from the fact exponent is just build using
make_expr
Joel Falcou wrote:
Eric Niebler a écrit :
_1 and _2 are in different domains, but _1(_2) is allowed and is in the domain of _1. That's why the expression "_1(_2) + _1" is permitted, but "_1(_2) + _2" is not.
You might have to post your code for us to get to the bottom of this. Could it come from the fact exponent is just build using
make_expr
and not proto::operator() ?
Oh, you're using make_expr. If the result of exponent(x) is always in
the domain of simd_domain
Eric Niebler a écrit :
Oh, you're using make_expr. If the result of exponent(x) is always in the domain of simd_domain
, then you should use that as the domain parameter to make_expr instead of domain_of<T>::type. Ha, right ! Forgot about domain_of. It fixes this indeed.
Concerning the other approach, I guess it boils down to have terminal of the given function object laying around? terminal< exponent_ > exponent ={{}}; How does it scale with a large number of function object (say > 300) in term of compile time ? Is there any advantage over make_expr ? -- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35
Joel Falcou wrote:
Eric Niebler a écrit :
Oh, you're using make_expr. If the result of exponent(x) is always in the domain of simd_domain
, then you should use that as the domain parameter to make_expr instead of domain_of<T>::type. Ha, right ! Forgot about domain_of. It fixes this indeed.
Cool.
Concerning the other approach, I guess it boils down to have terminal of the given function object laying around?
terminal< exponent_ > exponent ={{}}; ----------------------^ ::type here
Right, although it would change the resulting tree, because exponent(x) would have tag type proto::tag::function instead of nt2::tag::exponent_. You'd have to make corresponding changes to your grammar.
How does it scale with a large number of function object (say > 300) in term of compile time ? Is there any advantage over make_expr ?
Hard to say. The only advice I can give is to try it and see. -- Eric Niebler BoostPro Computing http://www.boostpro.com
Eric Niebler a écrit :
Cool. Small variation. If I want the domain of A(B) always be X, I just specify it with make_expr ?
Concerning the other approach, I guess it boils down to have terminal of the given function object laying around?
terminal< exponent_ > exponent ={{}}; ----------------------^ ::type here
Right, although it would change the resulting tree, because exponent(x) would have tag type proto::tag::function instead of nt2::tag::exponent_. You'd have to make corresponding changes to your grammar. To be abel to be called and produce reuslts, exponent_ just need to be a Polymorphic Function Object I assume ? Hard to say. The only advice I can give is to try it and see. Seems I found my occupation for this week-end then. My main concern is that having lots of declared but unused const object may force the compiler to compile all fo them aka ending in a verrrrrrry long compile-time and prolly large executable too.
-- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35
Joel Falcou wrote:
Eric Niebler a écrit :
Cool.
Small variation. If I want the domain of A(B) always be X, I just specify it with make_expr ?
Yes, or else make A a Proto terminal in the X domain.
Concerning the other approach, I guess it boils down to have terminal of the given function object laying around?
terminal< exponent_ > exponent ={{}}; ----------------------^ ::type here
Right, although it would change the resulting tree, because exponent(x) would have tag type proto::tag::function instead of nt2::tag::exponent_. You'd have to make corresponding changes to your grammar.
To be abel to be called and produce reuslts, exponent_ just need to be a Polymorphic Function Object I assume ?
Yes.
Hard to say. The only advice I can give is to try it and see.
Seems I found my occupation for this week-end then. My main concern is that having lots of declared but unused const object may force the compiler to compile all fo them aka ending in a verrrrrrry long compile-time and prolly large executable too.
You might be right. I'll be interested in your results. -- Eric Niebler BoostPro Computing http://www.boostpro.com
Eric Niebler a écrit :
Joel Falcou wrote:
Eric Niebler a écrit :
Cool.
Small variation. If I want the domain of A(B) always be X, I just specify it with make_expr ?
Yes, or else make A a Proto terminal in the X domain.
with : terminal< A_, X>::type A or by another mean ?? -- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35
Joel Falcou wrote:
Eric Niebler a écrit :
Joel Falcou wrote:
Eric Niebler a écrit :
Cool.
Small variation. If I want the domain of A(B) always be X, I just specify it with make_expr ?
Yes, or else make A a Proto terminal in the X domain.
with :
terminal< A_, X>::type A
or by another mean ??
In the usual way with a Proto extension. E.g.,
simd_expr
OK.
Last question. I changed my make_expr to use domain_of and
it worked nice for the base case.
Then I changed the domain of the
exponent thingy.
exponent takes a float/double vec adn return
an integral vec of the same size. So I gave to
simd_exprtag::exponent_ the same domain as vec<integer>. Now
I can build things like :
exponent(vf) + vi with the proper
type and everything works.
Now, I had some strange behavior in
my calalble_context. When I debug it, it seems that the type of
exponent(vf) is
simd_expr< vec
joel falcou wrote:
OK.
Last question. I changed my make_expr to use domain_of and it worked nice for the base case.
I'm confused. You *were* using domain_of and I told you not to. ???
Then I changed the domain of the exponent thingy.
exponent takes a float/double vec adn return an integral vec of the same size. So I gave to simd_exprtag::exponent_ the same domain as vec<integer>. Now I can build things like :
exponent(vf) + vi with the proper type and everything works.
Now, I had some strange behavior in my calalble_context. When I debug it, it seems that the type of exponent(vf) is
simd_expr< vec
, domain< simd_info > > instead of some :
simd_expr< bp::terminal
>, domain< simd_info > > So I don't how how to catch it in my context operator() overload.
For info, my exponent function is something like :
template<class A0> static inline typename proto::result_of::make_expr< tag::exponent_ , domain< make_integrer_vec<A0>::info_type > ----^^^^^^
What is domain here?
, A0 const&> exponent( A0 const a0) { return proto::make_expr< tag::exponent_ , domain< make_integrer_vec<A0>::info_type > >( boost::cref(a0)); }
Please post complete code that I can test. -- Eric Niebler BoostPro Computing http://www.boostpro.com
Eric Niebler a écrit :
joel falcou wrote:
OK.
Last question. I changed my make_expr to use domain_of and it worked nice for the base case.
I'm confused. You *were* using domain_of and I told you not to. ??? No, I wasn't and you did ;) What is domain here? template<class SIMDDescriptor> struct simd_domain : bp::domain< simd_generator<SIMDDescriptor> , simd_grammar {};
It's a template domain to go with the template generator of the tempalte expression.
Please post complete code that I can test. Here is a small test case :
http://codepad.org/x1U86VS9
I used string and lexical cast instead of real SIMD value cause the
amount of extra code was really large and because those two type
has the same non native casting properties than two different vector
types. This exhibits the same problem than I have currently aka
failure to properly evaluate the to_float expression which is an
expression of domain X with a child of domain Z.
The error log with g++ 4.3 is :
/usr/local/include/boost-1_38/boost/proto/context/callable.hpp||In
member function ‘typename boost::result_of
Joel Falcou wrote:
Eric Niebler a écrit :
joel falcou wrote:
OK.
Last question. I changed my make_expr to use domain_of and it worked nice for the base case.
I'm confused. You *were* using domain_of and I told you not to. ??? No, I wasn't and you did ;)
Still confused. <snip>
Here is a small test case :
Hey, that codepad thing is pretty cool. OK, I see the following in your
simd_context class:
template
Eric Niebler a écrit :
Still confused. Never mind, I did what was meant to be done ;) Hey, that codepad thing is pretty cool. It even *compiles* Boost code as the lib seems to be installed on the server. Saved me tons of time when caught in traffic jam with my PDA and a "oh snap!" moment occured ;)
The MPL assertion I added fired, and the type of X was "const simd_value
> &". You probably mean for terminals of that type to be handled by the following specialization, but its not because of the cv qualifier and the reference. Dang ... that was it :D Working flawlessly now.
Back on the initial topic, can't the assertion for discriminating domain in operators be added as a domain tempalte parameters usign a lambda ? like struct foo_domain : proto::domain< generator , grammar , is_same< domain_of<_1>, domain_of<_2> > > And use this lambda in the STATIC_ASSERT ? -- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35
Joel Falcou wrote:
Dang ... that was it :D Working flawlessly now.
Excellent.
Back on the initial topic, can't the assertion for discriminating domain in operators be added as a domain tempalte parameters usign a lambda ? like
struct foo_domain : proto::domain< generator , grammar , is_same< domain_of<_1>, domain_of<_2> > >
And use this lambda in the STATIC_ASSERT ?
That would associate the check with a domain. If there is an expression involving expressions from N different domains, you have N ways of checking for compatibility and no way to chose between them. -- Eric Niebler BoostPro Computing http://www.boostpro.com
participants (3)
-
Eric Niebler
-
joel falcou
-
Joel Falcou