Boost logo

Boost Users :

Subject: [Boost-users] [proto] generation of adaptive precision floating-point geometric predicates
From: Andrew Durward (andrew.durward_at_[hidden])
Date: 2010-03-19 17:36:25


Hi all,
I'm exploring the possibility of using proto to transform an expression (at
compile time) into a sequence of terms whose sum represents an increasingly
accurate floating-point approximation of the result. The underlying idea is
based on a paper by Shewchuk [1].

The central concept is that for any expression (a # b) where # is {+, -, *},
the result can be expressed as (x + y) where x is the floating-point
approximation of (a # b), and y is an error term whose value can also be
computed as a floating-point value.

In toying with proto, I've been able to transform simple expressions
successfully but I can't seem to figure out how to define a grammar that
will handle arbitrary combinations of {+, -, *} recursively. Here's what
I've got so far:

struct sum_approx{/* */};
struct sum_error{/* */};

struct diff_approx{/* */};
struct diff_error{/* */};

struct prod_approx{/* */};
struct prod_error{/* */};

struct Transform :
    proto::or_<
        proto::when<
            proto::plus< proto::terminal< _ >, proto::terminal< _ > >
          , fusion::cons<
                proto::_make_function(
                    sum_approx()
                  , proto::_left
                  , proto::_right
                )
              , fusion::cons<
                    proto::_make_function(
                        sum_error()
                      , proto::_left
                      , proto::_right
                    )
>
>()
>
        // ... similar substitutions for minus and multiplies
>
{};

So the expression (a + b) yields the sequence:
sum_approx(a,b)
sum_error(a,b)

Here's where I'm stuck. In the case of the expression (a + b)*(c - d), the
addition and subtraction should be replaced by the appropriate sequences
before the multiplication gets expanded to yield the final sequence:
prod_approx( sum_approx(a,b), diff_approx(c,d) )
prod_error( sum_approx(a,b), diff_approx(c,d) )
prod_approx( sum_approx(a,b), diff_error(c,d) )
prod_error( sum_approx(a,b), diff_error(c,d) )
prod_approx( sum_error(a,b), diff_approx(c,d) )
prod_error( sum_error(a,b), diff_approx(c,d) )
prod_approx( sum_error(a,b), diff_error(c,d) )
prod_error( sum_error(a,b), diff_error(c,d) )

Obviously I need a recursive transform here but I'm not sure how to pass it
the sequences generated by both the left and right subtrees.

struct Transform :
    proto::or_<
        // ... as before
      , proto::when<
            proto::multiplies< Transform, Transform >
          , /* WHAT_GOES_HERE */<
                Transform( proto::_left )
              , Transform( proto::_right )
>
>
>
{};

What exactly do I need here? A metafunction to generate the proper
sequence? What's the proper syntax to invoke it?

Can anybody point me in the right direction?

Thanks for any help,
andrew

[1] Shewchuk, Jonathon. Robust Adaptive Floating-Point Geometric
Predicates.
http://www.cs.cmu.edu/afs/cs/project/quake/public/papers/robust-predicates.p
s


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net