|
Boost : |
From: Matthias Troyer (troyer_at_[hidden])
Date: 2002-05-12 12:55:53
Hi all,
When using boost::random for a generic eigenvalue library that
we are developing (http://www.comp-phys.org/software/ietl)
we realized an issue regarding copy constructors of
Boost random number generators in particular, and actually
all generators.
The definition of std::generate in the C++ standard:
template<class ForwardIterator, class Generator>
void generate(ForwardIterator first, ForwardIterator last,
Generator gen);
requires Generator to be copy-constructible. But what is
the semantics of the copy constructor? If we call
generate twice, do we get the same sequence or not:
std::vector<T> x(100);
std::vector<T> y(100);
std::generate(x.begin(),x.end(),gen);
std::generate(y.begin(),y.end(),gen);
Is x==y, or not? In the current boost::random this depends on the
generator:
i) if gen is a boost::random generator, such as
boost::lagged_fibonacci607
we have x==y, since the generator is copied fully.
ii) if gen is a reference: boost::ref(gen), x!=y since we just copy
references,
and the std::generate functions modify the original generator.
iii) if gen is boost::uniform_01(gen), we have x!=y, since the
boost::uniform_01
adaptors store references to the original generator.
The behavior of ii) is perfectly OK, and is what anybody would expect.
The behavior of i) and iii), where both are boost::random generators
are not consistent. Thus my question:
``What is the semantics of copying a Generator ''
In most application codes I had no problems so far, as long as I am
aware that
the semantics changes when using an adaptor. However, we now use
generators
in our generic eigenvalue library. In the Lanczos algorithm, we run an
iteration
starting from a specified (often random) initial vector to obtain the
eigenvalues.
We then rerun the iteration from the SAME starting vector to get the
eigenvectors.
Note that we cannot afford to keep a copy of the starting vector. The
vectors
we are now planning to work with have 3e9 entries, and are 24 GBytes in
size.
We used to assume that in the example above x==y, which was what we
wanted.
This worked as long as the generator was boost::lagged_fibonacci, which
is a floating point generator. But switching to a different generator,
like boost::uniform_01<boost::mt19937> changes the semantics of the copy
constructor and breaks our code.
Thus I want to discuss this issue here. My gut feeling is that we cannot
avoid
the inconsistent semantics and that our library has to leave it up to
the user
to provide a copy of the generator for the second part of the Lanczos
algorithm.
With best regards,
Matthias
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk