Boost logo

Proto :

Subject: Re: [proto] Inter-domain interaction - Question and bug ?
From: Eric Niebler (eric_at_[hidden])
Date: 2011-02-26 04:50:48

Sorry for the delay. I've been inundated.

On 2/24/2011 3:54 AM, Joel Falcou wrote:
> Hi,
> while adding function to my SIMD library built on proto. I stumbled into
> this problem:
> I have a template grammar/generator/domain that helps me not mixing
> vector of different type/cardinal.
> However some functions are designed to take vector of float and turn
> them into vector of int.
> I wrote one there (exponenbits) by just forcing the domain to be the one
> from int. When I call it alone, it works.
> But if I do exponentbits( some_float ) + some_int doesnt work.
> The error is just :
> /Users/joelfalcou/nt2/sandbox/proto.cpp:161:46: error: no match for
> 'operator+' in 'nt2::simd::exponentbits(((const nt2::simd::pack<float,
> 4ul>&)((const nt2::simd::pack<float, 4ul>*)(& x)))) + y'
> With none of the usual 'no proto_grammar in not_a_domain' error I got
> when I mix element of different grammar with each other.
> Now, if i turn the grammar into:
> ////////////////////////////////////////////////////////////////////////////////
> // the template grammar
> ////////////////////////////////////////////////////////////////////////////////
> template<class T, class C>
> struct grammar
> : boost::proto
> ::or_ < boost::proto::terminal< data<T,C> >
> , boost::proto::unary_expr<exponentbits_,
> grammar<boost::proto::_,C> >
> , boost::proto::
> and_< boost::proto::
> nary_expr < boost::proto::_
> , boost::proto::vararg< grammar<T,C> >
> , boost::proto::
> not_< boost::proto::or_ < boost::proto::
> address_of< grammar<T,C> >
> , boost::proto::
> dereference< grammar<T,C> >
> , boost::proto::
> comma < grammar<T,C>
> , grammar<T,C>
> {};
> It works. Alas, I have a potentially high and extensible set of such
> function (some being binary or ternary or w/e) and so I want
> some way to accept such constructs without an explicit list of supported
> function. nt2 currently has something like 17 such cross domain function.
> My question is why building such an expression:
> - make an error. Once I wrapped a terminal of domain Foo in domain Bar,
> it should be composable with other element of Bar domain
> - if this is an error, why dont I get the usual error of mixing wrong
> element with each other ?

When building a new node, Proto does two checks:

1) Are the sub-expressions domain-compatible? In your case, they are.
Both the LHS and the RHS are in the same domain: the int domain. Had
this check failed, you'd get the familiar no-common-domain error.

2) Does the new expression match the grammar of the common domain? When
this fails, you get the no-matching-overload-found error. Without this
check, there would be no way to control overloads with Proto grammars.
Now, does this new expression match your original grammar (without the
above hack)? No, it doesn't. Your grammar requires that all the data
terminals have a certain type, and that's not the case for the
expression you're returning.

> Mixing element from unrelated domain through such domain wrapping is a
> very valauble techniaues in EDSL in my opinion as it allows efficient
> operations to be done.

I agree.

> nt2 has a vector and covector class in different domain and transposing
> a vector yields a covector, and vice versa. Being able to just have
> somehting that wraps the vector terminal and change its semantic this
> way is very valuable.

Sure. This is pretty easy. I suggest you introduce an additional unary
node with a special tag that is recognized by your grammar. For
instance, exponentbits currently returns:

  unary_expr< exponentbits, arg >

Instead, make it return:

  unary_expr< exponentbits, unary_expr< hidedomain, arg > >

Now, add the following alternate to your grammar:

  unary_expr< hidedomain, _ >

Make sense?

Eric Niebler
BoostPro Computing

Proto list run by eric at