|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r73393 - in sandbox/bloom_filter/trunk/boost/bloom_filter: . detail
From: cpp.cabrera_at_[hidden]
Date: 2011-07-26 17:23:54
Author: alejandro
Date: 2011-07-26 17:23:52 EDT (Tue, 26 Jul 2011)
New Revision: 73393
URL: http://svn.boost.org/trac/boost/changeset/73393
Log:
Major refactoring on apply_hash:
- combined dynamic_apply_hash and apply_hash into a single meta-function.
Updated basic_bloom_filter and dynamic_bloom_filter:
- both use new version of apply_hash.
- added incompatible_size_exception for pairwise operations
Working on refactoring counting_apply_hash.
Bug:
- counting_bloom_filter: bin_exceptions do not trigger.
Text files modified:
sandbox/bloom_filter/trunk/boost/bloom_filter/basic_bloom_filter.hpp | 18 +++--
sandbox/bloom_filter/trunk/boost/bloom_filter/counting_bloom_filter.hpp | 42 +++++++-------
sandbox/bloom_filter/trunk/boost/bloom_filter/detail/apply_hash.hpp | 119 ++++++++++-----------------------------
sandbox/bloom_filter/trunk/boost/bloom_filter/detail/counting_apply_hash.hpp | 64 ++++++++++++++-------
sandbox/bloom_filter/trunk/boost/bloom_filter/detail/exceptions.hpp | 15 +++-
sandbox/bloom_filter/trunk/boost/bloom_filter/dynamic_bloom_filter.hpp | 65 +++++++++++++--------
6 files changed, 158 insertions(+), 165 deletions(-)
Modified: sandbox/bloom_filter/trunk/boost/bloom_filter/basic_bloom_filter.hpp
==============================================================================
--- sandbox/bloom_filter/trunk/boost/bloom_filter/basic_bloom_filter.hpp (original)
+++ sandbox/bloom_filter/trunk/boost/bloom_filter/basic_bloom_filter.hpp 2011-07-26 17:23:52 EDT (Tue, 26 Jul 2011)
@@ -12,11 +12,7 @@
#ifndef BOOST_BLOOM_FILTER_BLOOM_FILTER_HPP
#define BOOST_BLOOM_FILTER_BLOOM_FILTER_HPP 1
-/**
- * \author Alejandro Cabrera
- * \brief A generic Bloom filter providing compile-time unrolling
- * of hash function application.
- */
+
#include <cmath>
#include <bitset>
@@ -40,7 +36,10 @@
public:
typedef T value_type;
typedef T key_type;
+ typedef std::bitset<Size> bitset_type;
typedef HashFunctions hash_function_type;
+ typedef basic_bloom_filter<T, Size,
+ HashFunctions> this_type;
public:
basic_bloom_filter() {}
@@ -87,7 +86,8 @@
void insert(const T& t) {
static const unsigned N = mpl::size<HashFunctions>::value - 1;
- detail::apply_hash<N, T, Size, HashFunctions>::insert(t, bits);
+ detail::apply_hash<N,
+ this_type>::insert(t, bits);
}
template <typename InputIterator>
@@ -99,7 +99,9 @@
bool probably_contains(const T& t) const {
static const unsigned N = mpl::size<HashFunctions>::value - 1;
- return detail::apply_hash<N, T, Size, HashFunctions>::contains(t, bits);
+ return detail::
+ apply_hash<N,
+ this_type>::contains(t, bits);
}
void clear() {
@@ -133,7 +135,7 @@
const basic_bloom_filter<_T, _Size, _HashFunctions>&);
private:
- std::bitset<Size> bits;
+ bitset_type bits;
};
template<class _T, size_t _Size, class _HashFunctions>
Modified: sandbox/bloom_filter/trunk/boost/bloom_filter/counting_bloom_filter.hpp
==============================================================================
--- sandbox/bloom_filter/trunk/boost/bloom_filter/counting_bloom_filter.hpp (original)
+++ sandbox/bloom_filter/trunk/boost/bloom_filter/counting_bloom_filter.hpp 2011-07-26 17:23:52 EDT (Tue, 26 Jul 2011)
@@ -59,7 +59,7 @@
// can have internal fragmentation if the calculation for
// bins_per_slot has a remainder. The severity of the internal
// fragmentation is equal to the remainder * the number of slots.
- // this check prevents internal fragmentation
+ // This check prevents internal fragmentation
BOOST_STATIC_ASSERT( ((sizeof(Block) * 8) % BitsPerBin) == 0);
// a slot is one element position in the array
@@ -72,17 +72,16 @@
static const size_t mask =
static_cast<Block>(0 - 1) >> (slot_bits - BitsPerBin);
- private:
- typedef boost::array<Block, array_size> bucket_type;
- typedef typename bucket_type::iterator bucket_iterator;
- typedef typename bucket_type::const_iterator bucket_const_iterator;
-
public:
typedef T value_type;
typedef T key_type;
typedef HashFunctions hash_function_type;
typedef Block block_type;
+ typedef boost::array<Block, array_size> bucket_type;
+ typedef typename bucket_type::iterator bucket_iterator;
+ typedef typename bucket_type::const_iterator bucket_const_iterator;
+
public:
counting_bloom_filter()
{
@@ -130,13 +129,6 @@
size_t count() const {
size_t ret = 0;
- /*
- std::cout << "Num Bins: " << NumBins << "\n"
- << "Bins Per Slot: " << bins_per_slot << "\n"
- << "Bits Per Bin: " << BitsPerBin << "\n"
- << "Array Size: " << array_size << "\n";
- */
-
for (bucket_const_iterator i = this->bits.begin(),
end = this->bits.end();
i != end; ++i) {
@@ -144,14 +136,6 @@
size_t offset_bits = bin * BitsPerBin;
size_t target_bits = (*i >> offset_bits) & mask;
- /*
- std::cout << "(count) targeting pos: " << std::distance(i, end) - 1
- << " with offset: " << offset_bits
- << " and bin: " << bin
- << " with slot value: " << *i
- << " and bin value: " << target_bits << "\n";
- */
-
if (target_bits > 0)
++ret;
}
@@ -217,11 +201,27 @@
counting_bloom_filter& operator|=(const counting_bloom_filter& rhs)
{
+ const bucket_iterator this_end = this->bits.end();
+ bucket_iterator this_start = this->bits.begin();
+ bucket_iterator rhs_start = rhs.bits.begin();
+
+ for (; this_start != this_end; ++this_start, ++rhs_start) {
+ *this_start |= *rhs_start;
+ }
+
return *this;
}
counting_bloom_filter& operator&=(const counting_bloom_filter& rhs)
{
+ const bucket_iterator this_end = this->bits.end();
+ bucket_iterator this_start = this->bits.begin();
+ bucket_iterator rhs_start = rhs.bits.begin();
+
+ for (; this_start != this_end; ++this_start, ++rhs_start) {
+ *this_start &= *rhs_start;
+ }
+
return *this;
}
Modified: sandbox/bloom_filter/trunk/boost/bloom_filter/detail/apply_hash.hpp
==============================================================================
--- sandbox/bloom_filter/trunk/boost/bloom_filter/detail/apply_hash.hpp (original)
+++ sandbox/bloom_filter/trunk/boost/bloom_filter/detail/apply_hash.hpp 2011-07-26 17:23:52 EDT (Tue, 26 Jul 2011)
@@ -13,122 +13,67 @@
#ifndef BOOST_BLOOM_FILTER_APPLY_HASH_HPP
#define BOOST_BLOOM_FILTER_APPLY_HASH_HPP
-#include <bitset>
-#include <boost/dynamic_bitset.hpp>
#include <boost/mpl/at.hpp>
namespace boost {
namespace bloom_filters {
namespace detail {
- /*************************************************************************
- * static bloom filter
- ************************************************************************/
template <size_t N,
- typename T,
- size_t Size,
- class HashFunctions>
+ typename Container>
struct apply_hash
{
- static void insert(const T& t, std::bitset<Size>& _bits) {
- typedef typename boost::mpl::at_c<HashFunctions, N>::type Hash;
- static Hash hasher;
-
- _bits[hasher(t) % Size] = true;
- apply_hash<N-1, T, Size, HashFunctions>::insert(t, _bits);
- }
-
- static bool contains(const T& t, const std::bitset<Size>& _bits) {
- typedef typename boost::mpl::at_c<HashFunctions, N>::type Hash;
- static Hash hasher;
+ typedef typename Container::value_type value_type;
+ typedef typename Container::bitset_type bitset_type;
+ typedef typename Container::hash_function_type hash_function_type;
- return (_bits[hasher(t) % Size] &&
- apply_hash<N-1, T, Size, HashFunctions>::contains(t, _bits));
- }
- };
-
- template <typename T,
- size_t Size,
- class HashFunctions>
- struct apply_hash<0, T, Size, HashFunctions>
- {
- static void insert(const T& t, std::bitset<Size>& _bits) {
- typedef typename boost::mpl::at_c<HashFunctions, 0>::type Hash;
+ static void insert(const value_type& t,
+ bitset_type& _bits)
+ {
+ typedef typename boost::mpl::at_c<hash_function_type, N>::type Hash;
static Hash hasher;
- _bits[hasher(t) % Size] = true;
+ _bits[hasher(t) % _bits.size()] = true;
+ apply_hash<N-1, Container>::insert(t, _bits);
}
- static bool contains(const T& t, const std::bitset<Size>& _bits) {
- typedef typename boost::mpl::at_c<HashFunctions, 0>::type Hash;
+ static bool contains(const value_type& t,
+ const bitset_type& _bits)
+ {
+ typedef typename boost::mpl::at_c<hash_function_type, N>::type Hash;
static Hash hasher;
- return (_bits[hasher(t) % Size]);
+ return (_bits[hasher(t) % _bits.size()] &&
+ apply_hash<N-1, Container>::contains(t, _bits));
}
};
- /*************************************************************************
- * dynamic bloom filter
- ************************************************************************/
- template <size_t N,
- typename T,
- class HashFunctions,
- typename Block,
- class Allocator>
- struct dynamic_apply_hash
+ template <typename Container>
+ struct apply_hash<0, Container>
{
- static void insert(const T& t, boost::dynamic_bitset<Block, Allocator>& _bits,
- const size_t size) {
- typedef typename boost::mpl::at_c<HashFunctions, N>::type Hash;
- static Hash hasher;
-
- _bits[hasher(t) % size] = true;
- dynamic_apply_hash<N-1,
- T,
- HashFunctions,
- Block,
- Allocator>::insert(t, _bits, size);
- }
-
- static bool contains(const T& t,
- const boost::dynamic_bitset<Block, Allocator>& _bits,
- const size_t size) {
- typedef typename boost::mpl::at_c<HashFunctions, N>::type Hash;
- static Hash hasher;
+ typedef typename Container::value_type value_type;
+ typedef typename Container::bitset_type bitset_type;
+ typedef typename Container::hash_function_type hash_function_type;
- return (_bits[hasher(t) % size] &&
- dynamic_apply_hash<N-1,
- T,
- HashFunctions,
- Block,
- Allocator>::contains(t, _bits, size));
- }
- };
-
- template <typename T,
- class HashFunctions,
- typename Block,
- class Allocator>
- struct dynamic_apply_hash<0, T, HashFunctions, Block, Allocator>
- {
- static void insert(const T& t,
- boost::dynamic_bitset<Block, Allocator>& _bits,
- const size_t size) {
- typedef typename boost::mpl::at_c<HashFunctions, 0>::type Hash;
+ static void insert(const value_type& t,
+ bitset_type& _bits)
+ {
+ typedef typename boost::mpl::at_c<hash_function_type, 0>::type Hash;
static Hash hasher;
- _bits[hasher(t) % size] = true;
+ _bits[hasher(t) % _bits.size()] = true;
}
- static bool contains(const T& t,
- const boost::dynamic_bitset<Block, Allocator>& _bits,
- const size_t size) {
- typedef typename boost::mpl::at_c<HashFunctions, 0>::type Hash;
+ static bool contains(const value_type& t,
+ const bitset_type& _bits)
+ {
+ typedef typename boost::mpl::at_c<hash_function_type, 0>::type Hash;
static Hash hasher;
- return (_bits[hasher(t) % size]);
+ return (_bits[hasher(t) % _bits.size()]);
}
};
+
} // namespace detail
} // namespace bloom_filter
} // namespace boost
Modified: sandbox/bloom_filter/trunk/boost/bloom_filter/detail/counting_apply_hash.hpp
==============================================================================
--- sandbox/bloom_filter/trunk/boost/bloom_filter/detail/counting_apply_hash.hpp (original)
+++ sandbox/bloom_filter/trunk/boost/bloom_filter/detail/counting_apply_hash.hpp 2011-07-26 17:23:52 EDT (Tue, 26 Jul 2011)
@@ -18,6 +18,8 @@
#include <boost/array.hpp>
#include <boost/mpl/at.hpp>
+#include <boost/bloom_filter/detail/exceptions.hpp>
+
namespace boost {
namespace bloom_filters {
namespace detail {
@@ -43,11 +45,15 @@
typedef typename boost::mpl::at_c<HashFunctions, N>::type Hash;
static Hash hasher;
- size_t hash_val = Hash(t) % NumBins;
- size_t pos = hash_val / BinsPerSlot;
- size_t offset_bits = (hash_val % BinsPerSlot) * BitsPerBin;
+ const size_t hash_val = Hash(t) % NumBins;
+ const size_t pos = hash_val / BinsPerSlot;
+ const size_t offset_bits = (hash_val % BinsPerSlot) * BitsPerBin;
size_t target_bits = (_slots[pos] >> offset_bits) & MASK;
- ++target_bits;
+ ++target_bits;
+
+ if (target_bits == 0)
+ throw bin_overflow_exception();
+
_slots[pos] |= (target_bits << offset_bits);
counting_apply_hash<N-1, T, NumBins,
@@ -60,11 +66,16 @@
typedef typename boost::mpl::at_c<HashFunctions, N>::type Hash;
static Hash hasher;
- size_t hash_val = hasher(t) % NumBins;
- size_t pos = hash_val / BinsPerSlot;
- size_t offset_bits = (hash_val % BinsPerSlot) * BitsPerBin;
+ const size_t hash_val = hasher(t) % NumBins;
+ const size_t pos = hash_val / BinsPerSlot;
+ const size_t offset_bits = (hash_val % BinsPerSlot) * BitsPerBin;
size_t target_bits = (_slots[pos] >> offset_bits) & MASK;
+
+ if (target_bits == 0)
+ throw bin_underflow_exception();
+
--target_bits;
+
_slots[pos] |= (target_bits << offset_bits);
counting_apply_hash<N-1, T, NumBins,
@@ -77,10 +88,10 @@
typedef typename boost::mpl::at_c<HashFunctions, N>::type Hash;
static Hash hasher;
- size_t hash_val = hasher(t) % NumBins;
- size_t pos = hash_val / BinsPerSlot;
- size_t offset_bits = (hash_val % BinsPerSlot) * BitsPerBin;
- size_t target_bits = (_slots[pos] >> offset_bits) & MASK;
+ const size_t hash_val = hasher(t) % NumBins;
+ const size_t pos = hash_val / BinsPerSlot;
+ const size_t offset_bits = (hash_val % BinsPerSlot) * BitsPerBin;
+ const size_t target_bits = (_slots[pos] >> offset_bits) & MASK;
return ((target_bits > 0) &&
counting_apply_hash<N-1, T, NumBins,
@@ -115,11 +126,16 @@
<< " incoming value: " << t << "\n";
*/
- size_t hash_val = hasher(t) % NumBins;
- size_t pos = hash_val / BinsPerSlot;
- size_t offset_bits = (hash_val % BinsPerSlot) * BitsPerBin;
+ const size_t hash_val = hasher(t) % NumBins;
+ const size_t pos = hash_val / BinsPerSlot;
+ const size_t offset_bits = (hash_val % BinsPerSlot) * BitsPerBin;
size_t target_bits = (_slots[pos] >> offset_bits) & MASK;
+
++target_bits;
+
+ if (target_bits == 0)
+ throw bin_overflow_exception();
+
_slots[pos] &= ~(MASK << offset_bits);
_slots[pos] |= (target_bits << offset_bits);
@@ -146,11 +162,17 @@
<< " incoming value: " << t << "\n";
*/
- size_t hash_val = hasher(t) % NumBins;
- size_t pos = hash_val / BinsPerSlot;
- size_t offset_bits = (hash_val % BinsPerSlot) * BitsPerBin;
+ const size_t hash_val = hasher(t) % NumBins;
+ const size_t pos = hash_val / BinsPerSlot;
+ const size_t offset_bits = (hash_val % BinsPerSlot) * BitsPerBin;
size_t target_bits = (_slots[pos] >> offset_bits) & MASK;
+
+
+ if (target_bits == 0)
+ throw bin_underflow_exception();
+
--target_bits;
+
_slots[pos] &= ~(MASK << offset_bits);
_slots[pos] |= (target_bits << offset_bits);
@@ -177,10 +199,10 @@
<< " incoming value: " << t << "\n";
*/
- size_t hash_val = hasher(t) % NumBins;
- size_t pos = hash_val / BinsPerSlot;
- size_t offset_bits = (hash_val % BinsPerSlot) * BitsPerBin;
- size_t target_bits = (_slots[pos] >> offset_bits) & MASK;
+ const size_t hash_val = hasher(t) % NumBins;
+ const size_t pos = hash_val / BinsPerSlot;
+ const size_t offset_bits = (hash_val % BinsPerSlot) * BitsPerBin;
+ const size_t target_bits = (_slots[pos] >> offset_bits) & MASK;
/*
std::cout << "(contains) checked bits at pos " << pos
Modified: sandbox/bloom_filter/trunk/boost/bloom_filter/detail/exceptions.hpp
==============================================================================
--- sandbox/bloom_filter/trunk/boost/bloom_filter/detail/exceptions.hpp (original)
+++ sandbox/bloom_filter/trunk/boost/bloom_filter/detail/exceptions.hpp 2011-07-26 17:23:52 EDT (Tue, 26 Jul 2011)
@@ -19,20 +19,27 @@
namespace bloom_filters {
namespace detail {
- class underflow : public std::exception {
+ class bin_underflow_exception : public std::exception {
virtual const char *
what() const throw() {
- return "boost::bloom_filters::detail::underflow";
+ return "boost::bloom_filters::detail::bin_underflow_exception";
}
};
- class overrflow : public std::exception {
+ class bin_overflow_exception : public std::exception {
virtual const char *
what() const throw() {
- return "boost::bloom_filters::detail::overflow";
+ return "boost::bloom_filters::detail::bin_overflow_exception";
}
};
+ class incompatible_size_exception : public std::exception {
+ virtual const char *
+ what() const throw() {
+ return "boost::bloom_filters::detail::incompatible_size_exception";
+ }
+ };
+
} // namespace detail
} // namespace bloom_filter
} // namespace boost
Modified: sandbox/bloom_filter/trunk/boost/bloom_filter/dynamic_bloom_filter.hpp
==============================================================================
--- sandbox/bloom_filter/trunk/boost/bloom_filter/dynamic_bloom_filter.hpp (original)
+++ sandbox/bloom_filter/trunk/boost/bloom_filter/dynamic_bloom_filter.hpp 2011-07-26 17:23:52 EDT (Tue, 26 Jul 2011)
@@ -12,13 +12,8 @@
#ifndef BOOST_BLOOM_FILTER_DYNAMIC_BLOOM_FILTER_HPP
#define BOOST_BLOOM_FILTER_DYNAMIC_BLOOM_FILTER_HPP 1
-/**
- * \author Alejandro Cabrera
- * \brief A generic Bloom filter providing compile-time unrolling
- * of hash function application.
- */
+
#include <cmath>
-#include <cassert>
#include <boost/config.hpp>
#include <boost/mpl/vector.hpp>
@@ -26,6 +21,7 @@
#include <boost/dynamic_bitset.hpp>
#include <boost/bloom_filter/detail/apply_hash.hpp>
+#include <boost/bloom_filter/detail/exceptions.hpp>
#include <boost/bloom_filter/hash/default.hpp>
namespace boost {
@@ -41,19 +37,22 @@
typedef HashFunctions hash_function_type;
typedef Block block_type;
typedef Allocator allocator_type;
+ typedef dynamic_bitset<block_type, allocator_type> bitset_type;
+ typedef dynamic_bloom_filter<T, HashFunctions,
+ Block, Allocator> this_type;
public:
// constructors
dynamic_bloom_filter() {}
- explicit dynamic_bloom_filter(const size_t bit_capacity) : bits(bit_capacity) {}
+ explicit dynamic_bloom_filter(const size_t bit_capacity) :
+ bits(bit_capacity) {}
template <typename InputIterator>
- dynamic_bloom_filter(const size_t bit_capacity,
- const InputIterator start,
+ dynamic_bloom_filter(const InputIterator start,
const InputIterator end)
- : bits(bit_capacity)
+ : bits(std::distance(start, end) * 4)
{
for (InputIterator i = start; i != end; ++i)
this->insert(*i);
@@ -62,7 +61,7 @@
// query functions
static BOOST_CONSTEXPR size_t num_hash_functions() {
return mpl::size<HashFunctions>::value;
- };
+ }
double false_positive_rate() const {
const double n = static_cast<double>(this->bits.count());
@@ -71,11 +70,11 @@
static const double e =
2.718281828459045235360287471352662497757247093699959574966;
return std::pow(1 - std::pow(e, -k * n / m), k);
- };
+ }
size_t count() const {
return this->bits.count();
- };
+ }
size_t bit_capacity() const {
return this->bits.size();
@@ -88,8 +87,8 @@
// core operations
void insert(const T& t) {
static const unsigned N = mpl::size<HashFunctions>::value - 1;
- detail::dynamic_apply_hash<N, T, HashFunctions, Block, Allocator>::
- insert(t, bits, bits.size());
+ detail::apply_hash<N, this_type>::
+ insert(t, bits);
}
template <typename InputIterator>
@@ -102,8 +101,8 @@
bool probably_contains(const T& t) const {
static const unsigned N = mpl::size<HashFunctions>::value - 1;
return detail::
- dynamic_apply_hash<N, T, HashFunctions, Block, Allocator>::
- contains(t, bits, bits.size());
+ apply_hash<N, this_type>::
+ contains(t, bits);
}
// auxilliary operations
@@ -124,8 +123,10 @@
template <typename _T, typename _HashFunctions,
typename _Block, typename _Allocator>
- friend bool operator==(const dynamic_bloom_filter<_T, _HashFunctions, _Block, _Allocator>&,
- const dynamic_bloom_filter<_T, _HashFunctions, _Block, _Allocator>&);
+ friend bool operator==(const dynamic_bloom_filter<_T, _HashFunctions,
+ _Block, _Allocator>&,
+ const dynamic_bloom_filter<_T, _HashFunctions,
+ _Block, _Allocator>&);
template <typename _T, typename _HashFunctions,
typename _Block, typename _Allocator>
@@ -139,19 +140,25 @@
_Allocator>&);
dynamic_bloom_filter& operator|=(const dynamic_bloom_filter& rhs) {
- assert(this->bit_capacity() == rhs.bit_capacity());
+ if(this->bit_capacity() != rhs.bit_capacity()) {
+ throw detail::incompatible_size_exception();
+ }
+
this->bits |= rhs.bits;
return *this;
}
dynamic_bloom_filter& operator&=(const dynamic_bloom_filter& rhs) {
- assert(this->bit_capacity() == rhs.bit_capacity());
+ if(this->bit_capacity() != rhs.bit_capacity()) {
+ throw detail::incompatible_size_exception();
+ }
+
this->bits &= rhs.bits;
return *this;
}
private:
- dynamic_bitset<block_type, allocator_type> bits;
+ bitset_type bits;
};
template<class T, class HashFunctions,
@@ -164,7 +171,10 @@
HashFunctions,
Block, Allocator>& rhs)
{
- assert(lhs.bit_capacity() == rhs.bit_capacity());
+ if(lhs.bit_capacity() != rhs.bit_capacity()) {
+ throw detail::incompatible_size_exception();
+ }
+
dynamic_bloom_filter<T, HashFunctions, Block, Allocator> ret(lhs);
ret |= rhs;
return ret;
@@ -180,7 +190,10 @@
HashFunctions,
Block, Allocator>& rhs)
{
- assert(lhs.bit_capacity() == rhs.bit_capacity());
+ if(lhs.bit_capacity() != rhs.bit_capacity()) {
+ throw detail::incompatible_size_exception();
+ }
+
dynamic_bloom_filter<T, HashFunctions, Block, Allocator> ret(lhs);
ret &= rhs;
return ret;
@@ -197,6 +210,10 @@
HashFunctions,
Block, Allocator>& rhs)
{
+ if(lhs.bit_capacity() != rhs.bit_capacity()) {
+ throw detail::incompatible_size_exception();
+ }
+
return lhs.bits == rhs.bits;
}
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk