Boost logo

Boost :

From: Jens Maurer (jmaurer_at_[hidden])
Date: 2000-02-18 10:04:29


Beman Dawes wrote:

Thanks for the comments.

> * Is there a reason you didn't specify the interface to meet the
> RandomNumberGenerator requirements in 25.2.11
> [lib.alg.random.shuffle] by providing operator()(long) in addition to
> the Generator (operator()()) requirements?

Yes. The UniformRandomNumberGenerator requirements are written so that
you can plug in any random number generator you find in the literature
with minimal effort. For example, implementing L'Ecuyer's combined
linear congruential generator (from 1988) was just fun. And these
generators usually provide a uniform distribution on some integer
range.

However, implementing operator()(long n) is more difficult than it
may seem at first. The trivial (rng % n) is incorrect if the range
of the rng is smaller than n, and it is slightly incorrect if the range
is larger than n because of quantization effects. That means it is
a considerable burden for UniformRandomNumberGenerator implementors
to get operator()(long) correct. Thus, I provided a
random_number_generator template (whose implementation is still buggy
as described above) which implemenents the RandomNumberGenerator
requirements.

> * It often seems useful to be able to get the current rng value (via
> value() and/or a conversion operator) without stepping to the next
> value. It saves setting up a work variable just to hang on to the
> value through a few lines of code.

Hm... You're right, I did have to set up a temporary variable in a few
places myself.

> * Supplying operator++() seems to me to make the intent of user code
> clearer:
>
> some_rng_class rng;
> while ( ... )
> {
> f1(++rng); // call a function with a new rng value
> f2(rng); // call a function with the current rng value
> f2(rng.value()); // some prefer to avoid a conversion
> operator
> }

There shall never be an implicit conversion operator, that I feel quite
strongly about.

We've basically got the choice between three interfaces:

 (1) The Generator STL requirements, i.e. operator() (only)
 (2) operator++ / value()
 (3) Iterator in the STL sense, i.e. operator++ and operator*

For the basic random number generators (minstd_rand, mt19937 etc.),
(1) seems to be the most minimal, everything else is a decoration.
I shall provide decoration classes [TODO]. For the distribution functors
such as gaussian_distribution, which are intended for use by user
code, I am unbiased whether to integrate a non-minimal interface such
as (2) and (3).

What do the others on this list think?

I only tested with gcc 2.95.2 and gcc-very-recent-experimental
on Linux.
Thanks for testing with more compilers.

> * The hyphens in file names make me slightly nervous.

I'll fix the .cpp files [Done], I hope they're no problem for the HTML
files?

> * Another nit: holding source line lengths to a maximum of 80
> columns makes it easier to read and print code.

Yes, sir. :-) [Hopefully done]

> * I tried to compile random-test.cpp. Microsoft VC++ 6.0 sp3
> doesn't allow in class initializers, so gets errors on the following.
> Maybe some VC++ experts can suggest an easy way around.

> static const bool has_fixed_range = true;
> static const result_type min_value = 0;
> static const result_type max_value = static_cast<result_type>(-1);

We can replace this with non-compile-time constants, i.e. implement
member functions min() and max() and have an enum has_fixed_range = false.
This gets a x2 performance hit on some distribution functors, but I think
that's ok for a non-conforming compiler. [Done]

Can we please have a #define BOOST_NO_INCLASS_MEMBER_INITIALIZER
in <boost/config.hpp> to indicate violation of std:9.4.2/4?

> * Metrowerks CodeWarrior said this conversion was illegal:
>
> static const result_type max_value = static_cast<result_type>(-1);

Do we have any boost-compatible method which gives a compile-time constant
for the maximum of some integer type? std::numeric_limits<type>::max()
is obviously not up to the task. [Ugly work-around in place.]

> * Other CodeWarrior errors:
> Error : ambiguous access to overloaded function
> 'boost::rand48::rand48(long)'
> 'boost::rand48::rand48(unsigned long long)'
> random-test.cpp line 76 rand48 rnd(5);

My code is buggy. I changed rand48 to use int32_t instead, which is
more correct for 64bit machines anyway and solves the overload
problem. If it still does not work, we must have an explicit
cast to int32_t when we call the constructor or seed functions.

> This points up a problem: some platforms don't yet support long
> long; it isn't part of the C++ Standard so #ifdefs are needed, I am
> afraid.

The easy way out for now is not to provide those RNGs which require
uint64_t, if uint64_t is not available. [Done]

Can we please have a #define BOOST_STDINT_H_HAS_UINT64_T in
<boost/config.hpp>?
Note that, for 64bit machines, this may be different from
"HAS_ULONGLONG".
 
> * There is an undefined symbol in random.hpp: M_PI

Hm... That's in my <cmath> header. I just re-checked the standard,
and it really isn't guaranteed to be there. [Fixed]

Btw, I've guarded "using std::xxx" declarations with
#ifndef BOOST_NO_STDC_NAMESPACE.

I have replaced the files in the egroups vault.

Jens Maurer.


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