Boost logo

Boost :

From: Fernando Cacciola (fernando_cacciola_at_[hidden])
Date: 2003-04-04 18:17:15


Hi,

First question: I see that there is a phoenix subdirectory
under both boost/spirit and lib/spirit; does this mean
that pheonix is distributed with boost 1.30.0? or only part of it?

Second question: I'm trying to do something which I
think could be done with some of the functional programming
libraries and tools available here at boost, perhaps
in combination with other tools from elsewhere.

Consider this:

// Just two 2D vectors.
Vector2D v(1,1), u(2,2);

// A vector given by a vector expression.
Vector2D s = v + u ;

What I want is to have 's' not having a real value
but storing the _expression_ (v+u) instead,
so that if I subsequently do something like:

Vector2D t(3,3);
double dot = s * t ; // operator * is dot product

is the dot product operation who evaluates
's' to produce the result.

Similarly, I should be able to construct
even more complex expressions with other vector
operations, such as multiplication by a scalar,
which are evaluated only at certain specific
points.

I've been palying with PETE
(the Portable Expression Template Engine)
but all I can do is something like:

<some complex expression type>& s = v + u ;

but as soon as 's' is assigned to a Vector2D
it is fully evaluated.
Thus, I need to combine PETE with some sort
of lazy evaluation tool.

Can something like this be done with
(boost) Lambda, Bind or Phoenix?

FYI, what I'm trying to do is to combine
what is known as "floating-point filtering"
(explained below)
with expression templates+lazy evaluation
to allow the construction of geometric
objects via algebraic expressions.
Ideally, a user would be able to write
the following:

//********************************
// Objects created via ordinary construction
// (reduced form in FC terms)
//********************************

point a(0,0), b(10,10);
line D(a,b); // a diagonal line

point c(2,0), d(2,10);
line L1(c,d); // a vertical line at x=2

point e(2+epsilon,0), f(2+epsilon,10);
line L2(e,f); // a vertical line at x=2+espilon

//********************************
// Objects created via expressions
//********************************

/*
Here, the coordinates for points
i0,i1 are given by unevaluated
expressions.
*/

point i0 = intersect(L1,D);
point i1 = intersect(L2,D);

//********************************
// Application of lazy evaluation + floating-point filtering
//********************************

/*
Here, the member function
int line::ordering(p0,p1)
returns the relative ordering
of the input points along the
line w.r.t to the line orientation:
(i.e., if p0 is before p1, returns +1)
*/
int order = L1.ordering(i0,i1);

/*
The thing is that if points i0,i1
are given actual coordinates during
the intersection computation,
the ordering predicate will deal
with unaccurrate data already and won't
be able to give a correct result
no matter how fancy aritmetic it
uses.
OTOH, if i0,i1 can be internally
represented by the expressions
used for the intersection
computation, the ordering
predicate can use the
technique known as
"floating-point filtering":
evaluate the expression first
with standard double precision,
and if it detects loose of
significand data, do it again
with an unlimited precision
number type.

This technique has been used for years
but with entirely runtime algebraic number types
which mantain the expression tree dynamically
via software, which has really slow performance.

TIA,

Fernando Cacciola


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