|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r51212 - in sandbox/numeric_bindings/libs/numeric/bindings/tools: . templates templates/level1
From: rutger_at_[hidden]
Date: 2009-02-12 05:24:34
Author: rutger
Date: 2009-02-12 05:24:32 EST (Thu, 12 Feb 2009)
New Revision: 51212
URL: http://svn.boost.org/trac/boost/changeset/51212
Log:
Added support for value type declarations through templating system,
return types for BLAS, argument substitution for BLAS, and more.
Added:
sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/level1/
sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/level1/axpy.hpp (contents, props changed)
sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/level1/dot.hpp (contents, props changed)
sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/level1/iamax.hpp (contents, props changed)
sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/level1/rotg.hpp (contents, props changed)
sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/level1/rotm.hpp (contents, props changed)
sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/level1/rotmg.hpp (contents, props changed)
sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/level1/swap.hpp (contents, props changed)
Text files modified:
sandbox/numeric_bindings/libs/numeric/bindings/tools/bindings.py | 2
sandbox/numeric_bindings/libs/numeric/bindings/tools/blas_generator.py | 43 ++++++++++++++++--
sandbox/numeric_bindings/libs/numeric/bindings/tools/netlib.py | 91 ++++++++++++++++++++++++++++++++++++---
sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/blas.hpp | 24 ++++++---
sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/singleton_blas.hpp | 2
5 files changed, 139 insertions(+), 23 deletions(-)
Modified: sandbox/numeric_bindings/libs/numeric/bindings/tools/bindings.py
==============================================================================
--- sandbox/numeric_bindings/libs/numeric/bindings/tools/bindings.py (original)
+++ sandbox/numeric_bindings/libs/numeric/bindings/tools/bindings.py 2009-02-12 05:24:32 EST (Thu, 12 Feb 2009)
@@ -109,6 +109,8 @@
template = template.replace( "$SUBROUTINE", k )
template = template.replace( "$ARGUMENTS", ", ".join( arg_list ) )
+ template = template.replace( '$RETURN_TYPE', global_info_map[ k ][ 'return_value_type' ] )
+ template = template.replace( '$RETURN_STATEMENT', global_info_map[ k ][ 'return_statement' ] )
content += proper_indent( template )
content += '\n'
Modified: sandbox/numeric_bindings/libs/numeric/bindings/tools/blas_generator.py
==============================================================================
--- sandbox/numeric_bindings/libs/numeric/bindings/tools/blas_generator.py (original)
+++ sandbox/numeric_bindings/libs/numeric/bindings/tools/blas_generator.py 2009-02-12 05:24:32 EST (Thu, 12 Feb 2009)
@@ -613,6 +613,8 @@
sub_template = sub_template.replace( "$CALL_C_HEADER", ", ".join( lapack_arg_list ) )
sub_template = sub_template.replace( "$SUBROUTINE", subroutine )
sub_template = sub_template.replace( '$groupname', group_name.lower() )
+ sub_template = sub_template.replace( '$RETURN_TYPE', info_map[ subroutine ][ 'return_value_type' ] )
+ sub_template = sub_template.replace( '$RETURN_STATEMENT', info_map[ subroutine ][ 'return_statement' ] )
overloads += bindings.proper_indent( sub_template )
@@ -640,9 +642,11 @@
level1_template = ''
level2_template = ''
level1_template = template_map[ 'blas_level1' ]
+ level2_template = template_map[ 'blas_level2' ]
level0_arg_list = []
level1_arg_list = []
+ level2_arg_list = []
call_level1_arg_list = []
level1_type_arg_list = []
level1_assert_list = []
@@ -657,6 +661,8 @@
level1_type_arg_list += [ info_map[ subroutine ][ 'argument_map' ][ arg ][ 'code' ][ 'level_1_type' ] ]
if info_map[ subroutine ][ 'argument_map' ][ arg ][ 'code' ][ 'level_1_assert' ] != None:
level1_assert_list += [ info_map[ subroutine ][ 'argument_map' ][ arg ][ 'code' ][ 'level_1_assert' ] ]
+ if info_map[ subroutine ][ 'argument_map' ][ arg ][ 'code' ][ 'level_2' ] != None:
+ level2_arg_list += [ info_map[ subroutine ][ 'argument_map' ][ arg ][ 'code' ][ 'level_2' ] ]
# Level 1 replacements
level1_template = level1_template.replace( "$CALL_LEVEL0", ", ".join( level0_arg_list ) )
@@ -664,8 +670,28 @@
level1_template = level1_template.replace( "$LEVEL1", ", ".join( level1_arg_list ) )
level1_template = level1_template.replace( "$TYPES", ", ".join( level1_type_arg_list ) )
level1_template = level1_template.replace( "$ASSERTS", "\n ".join( level1_assert_list ) )
+ level1_template = level1_template.replace( '$RETURN_TYPE', info_map[ subroutine ][ 'level1_return_type' ] )
+ level1_template = level1_template.replace( '$RETURN_STATEMENT', info_map[ subroutine ][ 'return_statement' ] )
+
+ # Level 2 replacements
+ # some special stuff is done here, such as replacing real_type with a
+ # type-traits deduction, etc..
+ level2_template = level2_template.replace( "$LEVEL2", ", ".join( level2_arg_list ) )
+
+ if len(level1_type_arg_list)>0:
+ first_typename = level1_type_arg_list[0].split(" ")[-1]
+ first_typename_datatype = first_typename[0:6].lower() # 'matrix' or 'vector'
+ else:
+ first_typename = 'TODO'
+ first_typename_datatype = 'TODO'
+ level2_template = level2_template.replace( "$FIRST_TYPENAME", first_typename )
+ level2_template = level2_template.replace( "$TYPEOF_FIRST_TYPENAME", first_typename_datatype )
+ level2_template = level2_template.replace( "$CALL_LEVEL1", ", ".join( call_level1_arg_list ) )
+ level2_template = level2_template.replace( "$TYPES", ", ".join( level1_type_arg_list ) )
level1_map[ value_type ] = bindings.proper_indent( level1_template )
+ level2_map[ value_type ] = bindings.proper_indent( level2_template )
+
#
# LEVEL 1 and 2 FINALIZATION
@@ -682,6 +708,10 @@
for value_type in level1_map.keys():
level1 += level1_map[ value_type ]
+ level2 = ''
+ for value_type in level2_map.keys():
+ level2 += level2_map[ value_type ]
+
#
# handle addition of includes
#
@@ -698,6 +728,7 @@
result = result.replace( '$INCLUDES', includes_code )
result = result.replace( '$OVERLOADS', overloads )
result = result.replace( '$LEVEL1', level1 )
+ result = result.replace( '$LEVEL2', level2 )
result = result.replace( '$GROUPNAME', group_name )
result = result.replace( '$groupname', group_name.lower() )
@@ -781,14 +812,14 @@
value_type_groups = group_by_value_type( function_info_map )
routines = {}
-routines[ 'level_1' ] = {}
-routines[ 'level_1' ][ 'endings' ] = [ 'ROTG', 'OTMG', 'ROT', 'ROTM', 'SWAP', 'SCAL', 'COPY', 'AXPY', 'DOT', 'DOTU', 'DOTC', 'NRM2', 'ASUM', 'AMAX' ]
+routines[ 'level1' ] = {}
+routines[ 'level1' ][ 'endings' ] = [ 'ROTG', 'OTMG', 'ROT', 'ROTM', 'SWAP', 'SCAL', 'COPY', 'AXPY', 'DOT', 'DOTU', 'DOTC', 'NRM2', 'ASUM', 'AMAX' ]
-routines[ 'level_2' ] = {}
-routines[ 'level_2' ][ 'endings' ] = [ 'MV', 'SV', 'GER', 'GERU', 'GERC', 'HER', 'HPR', 'HER2', 'HPR2', 'SYR', 'SPR', 'SYR2' ]
+routines[ 'level2' ] = {}
+routines[ 'level2' ][ 'endings' ] = [ 'MV', 'SV', 'GER', 'GERU', 'GERC', 'HER', 'HPR', 'HER2', 'HPR2', 'SYR', 'SPR', 'SYR2' ]
-routines[ 'level_3' ] = {}
-routines[ 'level_3' ][ 'endings' ] = [ 'MM', 'RK', 'R2K', 'SM' ]
+routines[ 'level3' ] = {}
+routines[ 'level3' ][ 'endings' ] = [ 'MM', 'RK', 'R2K', 'SM' ]
for name in value_type_groups.keys():
found = False
Modified: sandbox/numeric_bindings/libs/numeric/bindings/tools/netlib.py
==============================================================================
--- sandbox/numeric_bindings/libs/numeric/bindings/tools/netlib.py (original)
+++ sandbox/numeric_bindings/libs/numeric/bindings/tools/netlib.py 2009-02-12 05:24:32 EST (Thu, 12 Feb 2009)
@@ -24,6 +24,14 @@
templates = {}
+
+
+def value_type( fortran_type ):
+ m_type_map = global_type_map
+ m_type_map[ 'COMPLEX' ] = 'fcomplex_t'
+ m_type_map[ 'COMPLEX*16' ] = 'dcomplex_t'
+ m_type_map[ 'DOUBLE COMPLEX' ] = 'dcomplex_t'
+ return m_type_map[ fortran_type ]
def c_type( name, properties ):
m_type_map = global_type_map
@@ -44,6 +52,7 @@
m_type_map = global_type_map
m_type_map[ 'COMPLEX' ] = 'traits::complex_f'
m_type_map[ 'COMPLEX*16' ] = 'traits::complex_d'
+ m_type_map[ 'DOUBLE COMPLEX' ] = 'traits::complex_d'
result = m_type_map[ properties[ 'value_type' ] ]
@@ -65,12 +74,14 @@
def call_c_type( name, properties ):
result = ''
if properties[ 'type' ] == 'vector' or properties[ 'type' ] == 'matrix':
- if properties[ 'value_type' ][ 0:7] == 'COMPLEX':
+ if properties[ 'value_type' ][ 0:7] == 'COMPLEX' or \
+ properties[ 'value_type' ] == 'DOUBLE COMPLEX':
result = 'traits::complex_ptr(' + name.lower() + ')'
else:
result = name.lower()
elif properties[ 'type' ] == 'scalar':
- if properties[ 'value_type' ][ 0:7] == 'COMPLEX':
+ if properties[ 'value_type' ][ 0:7] == 'COMPLEX' or \
+ properties[ 'value_type' ] == 'DOUBLE COMPLEX':
result = 'traits::complex_ptr(&' + name.lower() + ')'
else:
result = '&' + name.lower()
@@ -603,13 +614,18 @@
subroutine_found = False
subroutine_name = ''
subroutine_arguments = []
+ subroutine_return_type = None
+
code_line_nr = 0
while code_line_nr < len(code) and not subroutine_found:
- match_subroutine_name = re.compile( 'SUBROUTINE[ ]+([A-Z]+)\(([^\)]+)' ).search( code[ code_line_nr ] )
+ match_subroutine_name = re.compile( '(DOUBLE PRECISION FUNCTION|REAL FUNCTION|SUBROUTINE)[ ]+([A-Z]+)\(([^\)]+)' ).search( code[ code_line_nr ] )
if match_subroutine_name != None:
subroutine_found = True
- subroutine_name = match_subroutine_name.group( 1 )
- subroutine_arguments = match_subroutine_name.group( 2 ).replace( ' ', '' ).split( "," )
+ subroutine_name = match_subroutine_name.group( 2 )
+ subroutine_arguments = match_subroutine_name.group( 3 ).replace( ' ', '' ).split( "," )
+ if match_subroutine_name.group(1) != 'SUBROUTINE':
+ subroutine_return_type = " ".join( match_subroutine_name.group(1).split(" ")[0:-1] )
+
code_line_nr += 1
# If we could not find a subroutine, we quit at our earliest convenience
@@ -630,6 +646,7 @@
print "Arguments: ", len(subroutine_arguments),":",subroutine_arguments
print "Group name: ", subroutine_group_name
print "Variant: ", subroutine_value_type
+ print "Return: ", subroutine_return_type
# Now we have the names of the arguments. The code following the subroutine statement are
# the argument declarations. Parse those right now, splitting these examples
@@ -677,6 +694,39 @@
grouped_arguments[ 'by_' + s ][ argument_properties[ s ] ] = []
grouped_arguments[ 'by_' + s ][ argument_properties[ s ] ] += [ argument_name ]
+ # See if we are hard-forcing argument renaming aliases
+ # This is needed for BLAS. It has argument names that are tied to the
+ # value_type variant of the routine. E.g., daxpy has dx and dy, caxpy has
+ # cx and cy. This is confusing for the generator, so we replace it with
+ # x and y, if the command for that is issued in its template.
+ argument_replace_map = {}
+ argument_value_type_prepend_key = subroutine_group_name.lower() + '.' + subroutine_value_type + '.remove_argument_value_type_prepend'
+ if my_has_key( argument_value_type_prepend_key, template_map ):
+ arguments_to_do = template_map[ my_has_key( argument_value_type_prepend_key, template_map ) ].strip().split(",")
+ for argument_new_name in arguments_to_do:
+ argument_new_name = argument_new_name.strip()
+ # try to find the original argument with value type
+ # it's either from a complex or double variant,
+ # not as cleanly applied as we might say
+ if subroutine_value_type == 'complex':
+ prefixes = [ 'C', 'Z' ]
+ else:
+ prefixes = [ 'S', 'D' ]
+ # determine the original name
+ argument_with_value_type = ''
+ for prefix in prefixes:
+ try_name = prefix + argument_new_name
+ if try_name in subroutine_arguments:
+ argument_with_value_type = try_name
+ loc = subroutine_arguments.index( argument_with_value_type )
+ # replace in the overall subroutine arguments list
+ subroutine_arguments[ loc ] = argument_new_name
+ # rename the key in the argument map
+ # create a copy, delete the old
+ argument_replace_map[ argument_with_value_type ] = argument_new_name
+ argument_map[ argument_new_name ] = argument_map[ argument_with_value_type ]
+ del argument_map[ argument_with_value_type ]
+
# The next bulk load of information can be acquired from the comment fields,
# this is between "Purpose" and "Arguments". Locate those headers, and init with
# -1 so that we can check if they where found.
@@ -699,6 +749,19 @@
if purpose_line_nr > 0 and arguments_line_nr > 0:
subroutine_purpose = "//" + "\n//".join( comments[ purpose_line_nr+3:arguments_line_nr-1 ] )
+ # try to see if we are overriding the arguments piece
+ arguments_key = subroutine_group_name.lower() + '.' + subroutine_value_type + '.arguments'
+ if my_has_key( arguments_key, template_map ):
+ print arguments_line_nr, comment_line_nr
+ arguments_line_nr = len(comments)
+ comments += template_map[ my_has_key( arguments_key, template_map ) ].splitlines()
+ comments += [ '' ]
+
+ pp.pprint( comments )
+
+ pp.pprint( argument_map )
+
+
# Break up the comments
# Now, for each argument, locate its associated comment field
#
@@ -711,6 +774,8 @@
detected_blas_style = False
while comment_line_nr < len(comments) and not finished_the_last:
+ print comments[ comment_line_nr ]
+
# Example for LAPACK-style matching.
# 45 M (input) INTEGER
# 46 The number of rows of the matrix A. M >= 0.
@@ -720,6 +785,9 @@
if not detected_blas_style and match_lapack_style != None:
detected_lapack_style = True
argument_name = match_lapack_style.group(1)
+ # If we're replacing arguments, we should do se here as well.
+ if argument_replace_map.has_key( argument_name ):
+ argument_name = argument_replace_map[ argument_name ]
argument_map[ argument_name ][ 'comment_lines' ] = [ comment_line_nr ]
split_regex = re.compile( '\/| or ' )
argument_map[ argument_name ][ 'io' ] = split_regex.split( match_lapack_style.group(2) )
@@ -946,7 +1014,7 @@
for arg in tmp_result:
if arg not in argument_map.keys():
# variable not found, try user-defined variable definitions
- add_user_defined_args( arg, user_defined_arg_map, template_map, subroutine_group_name + '.' + subroutine_value_type )
+ args( arg, user_defined_arg_map, template_map, subroutine_group_name + '.' + subroutine_value_type )
argument_properties[ 'assert_size_args' ] = tmp_result
print "Using user-defined assert_size_args: ", tmp_result
@@ -1025,9 +1093,18 @@
info_map = {}
info_map[ 'arguments' ] = subroutine_arguments
info_map[ 'purpose' ] = subroutine_purpose
+ info_map[ 'return_type' ] = subroutine_return_type
info_map[ 'argument_map' ] = argument_map
info_map[ 'grouped_arguments' ] = grouped_arguments
-
+ if subroutine_return_type != None:
+ info_map[ 'return_value_type' ] = value_type( subroutine_return_type )
+ info_map[ 'level1_return_type' ] = 'value_type'
+ info_map[ 'return_statement' ] = 'return '
+ else:
+ info_map[ 'return_value_type' ] = 'void'
+ info_map[ 'level1_return_type' ] = 'void'
+ info_map[ 'return_statement' ] = ''
+
#
# Pass / check user-defined stuff right here.
#
Modified: sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/blas.hpp
==============================================================================
--- sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/blas.hpp (original)
+++ sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/blas.hpp 2009-02-12 05:24:32 EST (Thu, 12 Feb 2009)
@@ -29,13 +29,13 @@
$OVERLOADS}
$LEVEL1
-
+$LEVEL2
}}}} // namespace boost::numeric::bindings::blas
#endif
$TEMPLATE[blas_overloads]
- inline void $groupname( $LEVEL0 ) {
- BLAS_$SUBROUTINE( $CALL_C_HEADER );
+ inline $RETURN_TYPE $groupname( $LEVEL0 ) {
+ $RETURN_STATEMENTBLAS_$SUBROUTINE( $CALL_C_HEADER );
}
$TEMPLATE[blas_level1]
// value-type based template
@@ -43,15 +43,21 @@
struct $groupname_impl {
typedef ValueType value_type;
- typedef typename traits::type_traits<ValueType>::real_type real_type;
// templated specialization
template< $TYPES >
- static void compute( $LEVEL1 ) {
-#ifndef NDEBUG
- $ASSERTS
-#endif
- detail::$groupname( $CALL_LEVEL0 );
+ static $RETURN_TYPE compute( $LEVEL1 ) {
+ $RETURN_STATEMENTdetail::$groupname( $CALL_LEVEL0 );
}
};
+$TEMPLATE[blas_level2]
+// template function to call $groupname
+template< $TYPES >
+inline integer_t $groupname( $LEVEL2 ) {
+ typedef typename traits::$TYPEOF_FIRST_TYPENAME_traits< $FIRST_TYPENAME >::value_type value_type;
+ integer_t info(0);
+ $groupname_impl< value_type >::compute( $CALL_LEVEL1 );
+ return info;
+}
+
$TEMPLATE[end]
Added: sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/level1/axpy.hpp
==============================================================================
--- (empty file)
+++ sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/level1/axpy.hpp 2009-02-12 05:24:32 EST (Thu, 12 Feb 2009)
@@ -0,0 +1,11 @@
+$TEMPLATE[axpy.all.remove_argument_value_type_prepend]
+A,X,Y
+$TEMPLATE[axpy.all.arguments]
+ N (input) INTEGER
+ Dimension of array A
+ INCX (input) INTEGER
+ INCY (input) INTEGER
+ A (input) DATATYPE variable alpha
+ X (input) DATATYPE array of length (N)
+ Y (output) DATATYPE array of length (N)
+$TEMPLATE[end]
Added: sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/level1/dot.hpp
==============================================================================
--- (empty file)
+++ sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/level1/dot.hpp 2009-02-12 05:24:32 EST (Thu, 12 Feb 2009)
@@ -0,0 +1,10 @@
+$TEMPLATE[dot.all.remove_argument_value_type_prepend]
+X,Y
+$TEMPLATE[dot.all.arguments]
+ N (input) INTEGER
+ Dimension of array A
+ INCX (input) INTEGER
+ INCY (input) INTEGER
+ X (input) DATATYPE array of length (N)
+ Y (input) DATATYPE array of length (N)
+$TEMPLATE[end]
Added: sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/level1/iamax.hpp
==============================================================================
--- (empty file)
+++ sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/level1/iamax.hpp 2009-02-12 05:24:32 EST (Thu, 12 Feb 2009)
@@ -0,0 +1,7 @@
+$TEMPLATE[iamax.all.remove_argument_value_type_prepend]
+X
+$TEMPLATE[iamax.all.arguments]
+ N (input) INTEGER
+ INCX (input) INTEGER
+ X (input) DATATYPE
+$TEMPLATE[end]
Added: sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/level1/rotg.hpp
==============================================================================
--- (empty file)
+++ sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/level1/rotg.hpp 2009-02-12 05:24:32 EST (Thu, 12 Feb 2009)
@@ -0,0 +1,8 @@
+$TEMPLATE[rotg.all.remove_argument_value_type_prepend]
+A,B
+$TEMPLATE[rotg.all.arguments]
+ A (input/output) DATATYPE
+ B (input/output) DATATYPE
+ C (input/output) DATATYPE
+ S (input/output) DATATYPE
+$TEMPLATE[end]
Added: sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/level1/rotm.hpp
==============================================================================
--- (empty file)
+++ sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/level1/rotm.hpp 2009-02-12 05:24:32 EST (Thu, 12 Feb 2009)
@@ -0,0 +1,3 @@
+$TEMPLATE[rotm.all.remove_argument_value_type_prepend]
+X,Y,PARAM
+$TEMPLATE[end]
Added: sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/level1/rotmg.hpp
==============================================================================
--- (empty file)
+++ sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/level1/rotmg.hpp 2009-02-12 05:24:32 EST (Thu, 12 Feb 2009)
@@ -0,0 +1 @@
+$TEMPLATE[end]
Added: sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/level1/swap.hpp
==============================================================================
--- (empty file)
+++ sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/level1/swap.hpp 2009-02-12 05:24:32 EST (Thu, 12 Feb 2009)
@@ -0,0 +1,9 @@
+$TEMPLATE[swap.all.remove_argument_value_type_prepend]
+X,Y
+$TEMPLATE[swap.all.arguments]
+ N (input) INTEGER
+ INCX (input) INTEGER increment in X
+ INCY (input) INTEGER increment in Y
+ X (output) DATATYPE
+ Y (output) DATATYPE
+$TEMPLATE[end]
Modified: sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/singleton_blas.hpp
==============================================================================
--- sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/singleton_blas.hpp (original)
+++ sandbox/numeric_bindings/libs/numeric/bindings/tools/templates/singleton_blas.hpp 2009-02-12 05:24:32 EST (Thu, 12 Feb 2009)
@@ -27,7 +27,7 @@
#endif
$TEMPLATE[blas.h_function]
- void BLAS_$SUBROUTINE( $ARGUMENTS );
+ $RETURN_TYPE BLAS_$SUBROUTINE( $ARGUMENTS );
$TEMPLATE[blas_names.h]
//
// Copyright (c) 2003--2009
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