Boost logo

Boost :

From: Eric Niebler (eric_at_[hidden])
Date: 2008-03-28 03:56:10


Noah Stein wrote:
> Fernando Cacciola wrote:
>
>> 5) There is a reason why CGAL doesn't provide a distance function at all
> but
>> only a squared_distance, and I agree with that reason: sqrt() kills
>> robustness and distances are usually used for comparisons, so you seldom
>> need that.
>
> This is one of the things I think proto can help with. I'm playing around
> with a simple vector/point/matrix library just to get a feel for it. proto
> should be able to transform expressions of the sort "length(a) > length(b)"
> into "dot(a,a) > dot(b,b)". I think proper use of proto can lead to high
> levels of expressivity combined with good optimization.

Indeed, see below.

     #include <iostream>
     #include <boost/xpressive/proto/proto.hpp>
     #include <boost/xpressive/proto/debug.hpp>
     #include <boost/xpressive/proto/transform.hpp>
     using namespace boost;
     using namespace proto;

     struct length_impl
     {
         friend std::ostream &operator<<(std::ostream &sout, length_impl)
         {
             return sout << "length_impl";
         }
     };

     struct dot_impl
     {
         // dot implementation here
         friend std::ostream &operator<<(std::ostream &sout, dot_impl)
         {
             return sout << "dot_impl";
         }
     };

     terminal<length_impl>::type const length = {{}};
     terminal<dot_impl>::type const dot = {{}};

     // work around msvc bugs...
     #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
     #define dot_impl() make<dot_impl>
     #define _arg1(a) call<_arg1(a)>
     #define _make_function(a,b,c) call<_make_function(a,b,c)>
     #define _make_terminal(a) call<_make_terminal(a)>
     #endif

     // convert length(a) < length(b) to dot(a,a) < dot(b,b)
     struct Convert
       : when<
             less<
                 function<terminal<length_impl>, _>
               , function<terminal<length_impl>, _>
>
           , _make_less(
                 _make_function(
                     _make_terminal(dot_impl())
                   , _arg1(_arg0)
                   , _arg1(_arg0)
                 )
               , _make_function(
                     _make_terminal(dot_impl())
                   , _arg1(_arg1)
                   , _arg1(_arg1)
                 )
             )
>
     {};

     int main()
     {
         int i = 0;
         display_expr(length(1) < length(2));
         display_expr(Convert()(length(1) < length(2), i, i));
     }

This program prints:

     less(
         function(
             terminal(length_impl)
           , terminal(1)
         )
       , function(
             terminal(length_impl)
           , terminal(2)
         )
     )
     less(
         function(
             terminal(dot_impl)
           , terminal(1)
           , terminal(1)
         )
       , function(
             terminal(dot_impl)
           , terminal(2)
           , terminal(2)
         )
     )

In addition to demonstrating how to transform expressions, it's also a
neat demonstration of how buggy msvc is wrt function types. :-/

-- 
Eric Niebler
Boost Consulting
www.boost-consulting.com

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk