|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r56550 - in sandbox/itl: boost/itl libs/itl/test libs/itl/test/fastest_interval_map_ libs/itl/test/fastest_split_interval_map_ libs/itl/test/test_casual_ libs/itl/test/test_interval_map_ libs/itl/test/test_split_interval_map_
From: afojgo_at_[hidden]
Date: 2009-10-03 06:34:26
Author: jofaber
Date: 2009-10-03 06:34:24 EDT (Sat, 03 Oct 2009)
New Revision: 56550
URL: http://svn.boost.org/trac/boost/changeset/56550
Log:
Refactoring, additions: Feedback by Jeff Flinn revealed that support for std::inserter was not working.
Fixed std::inserter support. Added tests of std::copy using std::inserter. Stable {msvc-8.0, 9.0}
Added:
sandbox/itl/libs/itl/test/test_functions.hpp (contents, props changed)
Text files modified:
sandbox/itl/boost/itl/interval_base_map.hpp | 17 ++++++++-
sandbox/itl/boost/itl/interval_base_set.hpp | 13 +++++++
sandbox/itl/boost/itl/interval_map.hpp | 33 +++++++++++++++++
sandbox/itl/boost/itl/split_interval_map.hpp | 33 +++++++++++++++++
sandbox/itl/libs/itl/test/fastest_interval_map_/fastest_interval_map.cpp | 1
sandbox/itl/libs/itl/test/fastest_interval_map_cases.hpp | 4 ++
sandbox/itl/libs/itl/test/fastest_split_interval_map_/fastest_split_interval_map.cpp | 1
sandbox/itl/libs/itl/test/test_casual_/test_casual.cpp | 74 +++++++++------------------------------
sandbox/itl/libs/itl/test/test_interval_map_/test_interval_map.cpp | 5 +-
sandbox/itl/libs/itl/test/test_interval_map_cases.hpp | 4 ++
sandbox/itl/libs/itl/test/test_interval_map_shared.hpp | 37 ++++++++++++++++++++
sandbox/itl/libs/itl/test/test_split_interval_map_/test_split_interval_map.cpp | 1
12 files changed, 160 insertions(+), 63 deletions(-)
Modified: sandbox/itl/boost/itl/interval_base_map.hpp
==============================================================================
--- sandbox/itl/boost/itl/interval_base_map.hpp (original)
+++ sandbox/itl/boost/itl/interval_base_map.hpp 2009-10-03 06:34:24 EDT (Sat, 03 Oct 2009)
@@ -151,6 +151,10 @@
/// const_iterator for iteration over intervals
typedef typename ImplMapT::const_reverse_iterator const_reverse_iterator;
+ typedef typename ImplMapT::pointer pointer;
+ typedef typename ImplMapT::const_pointer const_pointer;
+ typedef typename ImplMapT::reference reference;
+ typedef typename ImplMapT::const_reference const_reference;
public:
inline static bool has_symmetric_difference()
@@ -409,8 +413,17 @@
/** Insertion of an \c interval_value_pair into the map. */
SubType& insert(const segment_type& interval_value_pair)
- { that()->insert_(interval_value_pair); return *that(); }
-
+ {
+ that()->insert_(interval_value_pair);
+ return *that();
+ }
+
+ /** Insertion of an \c interval_value_pair into the map. Iterator \c prior_.
+ serves as a hint to insert after the element \c prior point to. */
+ iterator insert(iterator prior_, const segment_type& interval_value_pair)
+ {
+ return that()->insert_(prior_, interval_value_pair);
+ }
/** With <tt>key_value_pair = (k,v)</tt> set value \c v for key \c k */
SubType& set(const element_type& key_value_pair)
Modified: sandbox/itl/boost/itl/interval_base_set.hpp
==============================================================================
--- sandbox/itl/boost/itl/interval_base_set.hpp (original)
+++ sandbox/itl/boost/itl/interval_base_set.hpp 2009-10-03 06:34:24 EDT (Sat, 03 Oct 2009)
@@ -116,6 +116,11 @@
/// const_iterator for iteration over intervals
typedef typename ImplSetT::const_reverse_iterator const_reverse_iterator;
+ typedef typename ImplSetT::pointer pointer;
+ typedef typename ImplSetT::const_pointer const_pointer;
+ typedef typename ImplSetT::reference reference;
+ typedef typename ImplSetT::const_reference const_reference;
+
enum { fineness = 4 }; //SubType::fineness };
public:
@@ -289,6 +294,14 @@
SubType& insert(const segment_type& inter_val)
{ return add(inter_val); }
+ /** Insert an interval of elements \c inter_val to the set. Iterator
+ \c prior_ is a hint to the position \c inter_val can be
+ inserted after. */
+ iterator insert(iterator prior_, const segment_type& inter_val)
+ { return that()->add_(prior_, inter_val); }
+
+
+
/** Erase an element \c key from the set */
SubType& erase(const element_type& key)
{ return subtract(interval_type(key)); }
Modified: sandbox/itl/boost/itl/interval_map.hpp
==============================================================================
--- sandbox/itl/boost/itl/interval_map.hpp (original)
+++ sandbox/itl/boost/itl/interval_map.hpp 2009-10-03 06:34:24 EDT (Sat, 03 Oct 2009)
@@ -129,6 +129,7 @@
void subtract_(const value_type&);
void insert_(const value_type& value);
+ iterator insert_(iterator prior_, const value_type& value);
void erase_(const value_type& value);
private:
@@ -616,6 +617,36 @@
}
}
+template <typename DomainT, typename CodomainT, class Traits,
+ ITL_COMPARE Compare, ITL_COMBINE Combine, ITL_SECTION Section, template<class,ITL_COMPARE>class Interval, ITL_ALLOC Alloc>
+inline typename interval_map<DomainT,CodomainT,Traits,Compare,Combine,Section,Interval,Alloc>::iterator
+ interval_map<DomainT,CodomainT,Traits,Compare,Combine,Section,Interval,Alloc>
+ ::insert_(iterator prior_, const value_type& addend)
+{
+ interval_type inter_val = addend.first;
+ if(inter_val.empty())
+ return prior_;
+
+ const CodomainT& co_val = addend.second;
+ if(Traits::absorbs_neutrons && co_val==codomain_combine::neutron())
+ return prior_;
+
+ std::pair<iterator,bool> insertion
+ = this->template map_insert<codomain_combine>(prior_, inter_val, co_val);
+
+ if(insertion.second)
+ return join_neighbours(insertion.first);
+ {
+ // Detect the first and the end iterator of the collision sequence
+ std::pair<iterator,iterator> overlap = this->_map.equal_range(inter_val);
+ iterator it_ = overlap.first,
+ last_ = overlap.second;
+ --last_;
+ insert_range(inter_val, co_val, it_, last_);
+ return it_;
+ }
+}
+
template <typename DomainT, typename CodomainT, class Traits,
ITL_COMPARE Compare, ITL_COMBINE Combine, ITL_SECTION Section, template<class,ITL_COMPARE>class Interval, ITL_ALLOC Alloc>
@@ -653,7 +684,7 @@
if(!end_gap.empty())
{
inserted_ = this->_map.insert(prior_, value_type(end_gap, co_val));
- join_neighbours(inserted_);
+ it_ = join_neighbours(inserted_);
}
}
Modified: sandbox/itl/boost/itl/split_interval_map.hpp
==============================================================================
--- sandbox/itl/boost/itl/split_interval_map.hpp (original)
+++ sandbox/itl/boost/itl/split_interval_map.hpp 2009-10-03 06:34:24 EDT (Sat, 03 Oct 2009)
@@ -125,6 +125,7 @@
void subtract_(const value_type&);
void insert_(const value_type& value);
+ iterator insert_(iterator, const value_type& value);
void erase_(const value_type& value);
private:
@@ -482,6 +483,36 @@
}
}
+template <typename DomainT, typename CodomainT, class Traits,
+ ITL_COMPARE Compare, ITL_COMBINE Combine, ITL_SECTION Section, template<class,ITL_COMPARE>class Interval, ITL_ALLOC Alloc>
+inline typename split_interval_map<DomainT,CodomainT,Traits,Compare,Combine,Section,Interval,Alloc>::iterator
+ split_interval_map<DomainT,CodomainT,Traits,Compare,Combine,Section,Interval,Alloc>
+ ::insert_(iterator prior_, const value_type& addend)
+{
+ interval_type inter_val = addend.first;
+ if(inter_val.empty())
+ return prior_;
+
+ const CodomainT& co_val = addend.second;
+ if(Traits::absorbs_neutrons && co_val==codomain_combine::neutron())
+ return prior_;
+
+ std::pair<iterator,bool> insertion
+ = this->template map_insert<codomain_combine>(prior_, inter_val, co_val);
+
+ if(insertion.second)
+ return insertion.first;
+ {
+ // Detect the first and the end iterator of the collision sequence
+ std::pair<iterator,iterator> overlap = this->_map.equal_range(inter_val);
+ iterator it_ = overlap.first,
+ last_ = overlap.second;
+ --last_;
+ insert_range(inter_val, co_val, it_, last_);
+ return it_;
+ }
+}
+
template <typename DomainT, typename CodomainT, class Traits,
ITL_COMPARE Compare, ITL_COMBINE Combine, ITL_SECTION Section, template<class,ITL_COMPARE>class Interval, ITL_ALLOC Alloc>
@@ -512,7 +543,7 @@
//insert_rear(rest_interval, co_val, last_):
interval_type end_gap = left_subtract(rest_interval, last_interval);
if(!end_gap.empty())
- inserted_ = this->_map.insert(prior_, value_type(end_gap, co_val));
+ it_ = this->_map.insert(prior_, value_type(end_gap, co_val));
}
Modified: sandbox/itl/libs/itl/test/fastest_interval_map_/fastest_interval_map.cpp
==============================================================================
--- sandbox/itl/libs/itl/test/fastest_interval_map_/fastest_interval_map.cpp (original)
+++ sandbox/itl/libs/itl/test/fastest_interval_map_/fastest_interval_map.cpp 2009-10-03 06:34:24 EDT (Sat, 03 Oct 2009)
@@ -13,6 +13,7 @@
// interval instance types
#include "../test_type_lists.hpp"
#include "../test_value_maker.hpp"
+#include "../test_functions.hpp"
#include <boost/itl/interval_map.hpp>
#include <boost/itl/separate_interval_set.hpp>
Modified: sandbox/itl/libs/itl/test/fastest_interval_map_cases.hpp
==============================================================================
--- sandbox/itl/libs/itl/test/fastest_interval_map_cases.hpp (original)
+++ sandbox/itl/libs/itl/test/fastest_interval_map_cases.hpp 2009-10-03 06:34:24 EDT (Sat, 03 Oct 2009)
@@ -71,6 +71,10 @@
(fastest_itl_interval_map_inclusion_compare_4_bicremental_types)
{ interval_map_inclusion_compare_4_bicremental_types<discrete_type_4, int, partial_absorber, INTERVAL_MAP>();}
+BOOST_AUTO_TEST_CASE
+(fastest_itl_interval_map_std_copy_via_inserter_4_bicremental_types)
+{ interval_map_std_copy_via_inserter_4_bicremental_types<bicremental_type_4, int, partial_absorber, INTERVAL_MAP>();}
+
#endif // BOOST_ITL_FASTEST_INTERVAL_MAP_CASES_HPP_JOFA_090702
Modified: sandbox/itl/libs/itl/test/fastest_split_interval_map_/fastest_split_interval_map.cpp
==============================================================================
--- sandbox/itl/libs/itl/test/fastest_split_interval_map_/fastest_split_interval_map.cpp (original)
+++ sandbox/itl/libs/itl/test/fastest_split_interval_map_/fastest_split_interval_map.cpp 2009-10-03 06:34:24 EDT (Sat, 03 Oct 2009)
@@ -14,6 +14,7 @@
// interval instance types
#include "../test_type_lists.hpp"
#include "../test_value_maker.hpp"
+#include "../test_functions.hpp"
#include <boost/itl/separate_interval_set.hpp>
#include <boost/itl/split_interval_set.hpp>
Modified: sandbox/itl/libs/itl/test/test_casual_/test_casual.cpp
==============================================================================
--- sandbox/itl/libs/itl/test/test_casual_/test_casual.cpp (original)
+++ sandbox/itl/libs/itl/test/test_casual_/test_casual.cpp 2009-10-03 06:34:24 EDT (Sat, 03 Oct 2009)
@@ -7,6 +7,7 @@
+-----------------------------------------------------------------------------*/
#define BOOST_TEST_MODULE itl::casual unit test
#include <string>
+#include <vector>
#include <boost/mpl/list.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/test/test_case_template.hpp>
@@ -35,62 +36,21 @@
{
typedef int T;
typedef int U;
- typedef itl::map<int,int> ItlMapT;
- typedef itl::set<int> ItlSetT;
- typedef interval_map<int,int,partial_enricher> IntervalMapT;
- typedef split_interval_map<int,int> SplitIntervalMapT;
- typedef interval_set<int> IntervalSetT;
- typedef split_interval_set<int> SplitIntervalSetT;
-
- const bool test = is_same<SplitIntervalSetT::key_type, SplitIntervalSetT::interval_type>::value;
- BOOST_CHECK_EQUAL(test, true);
-
- SplitIntervalSetT spliss;
- spliss.add(I_D(1,3)).add(I_D(3,4)).add(I_D(4,6)).add(I_D(6,8));
- spliss.contains(I_D(2,5));
- BOOST_CHECK_EQUAL(spliss.contains(I_D(2,7)), true);
- BOOST_CHECK_EQUAL(intersects(spliss, I_D(2,7)), true);
- BOOST_CHECK_EQUAL(intersects(spliss, MK_v(2)), true);
-
- ItlMapT map_a(make_pair(1,1));
- ItlSetT set_a(1);
- map_a.add(make_pair(2,1));
- set_a.add(2);
- bool its = Map::intersects(map_a, map_a);
-
- erase(map_a, set_a);
- BOOST_CHECK_EQUAL(erase(map_a, set_a), ItlMapT());
- BOOST_CHECK_EQUAL(erase(map_a, map_a), ItlMapT());
-
- itl::map<int,int,total_absorber> tomp_a, tomp_b, tomp_c;
- tomp_a.add(make_pair(1,1)).add(make_pair(2,1));
-
- BOOST_CHECK_EQUAL((tomp_a & tomp_b).empty(), false);
- BOOST_CHECK_EQUAL((tomp_b & tomp_c).empty(), true);
-
- interval_map<int, interval_set<int> > maose, maose2;
- interval_set<int> inse;
- inse.add(I_I(1,4));
-
- maose.add(make_pair(I_I(1,4), inse));
- maose2 = maose;
- maose2.add(make_pair(I_I(5,6), inse));
-
-
- BOOST_CHECK_EQUAL(maose2.contains(maose), true);
-
- itl::set<int> eleset_a, eleset_a2, eleset_b, eleset_c;
- //eleset_a.add(1).add(2).add(5).add(8).add(11);
- eleset_a.add(8).add(11);
- eleset_a2 = eleset_a;
- eleset_b.add(8).add(2).add(11);
- eleset_c.add(9);
-
- //BOOST_CHECK_EQUAL(Set::inclusion_compare(eleset_a, eleset_a2), inclusion::equal);
- //BOOST_CHECK_EQUAL(Set::inclusion_compare(eleset_a, eleset_b), inclusion::superset);
- //BOOST_CHECK_EQUAL(Set::inclusion_compare(eleset_b, eleset_a), inclusion::subset);
-
- inclusion_compare(eleset_a, eleset_c);
- BOOST_CHECK_EQUAL(inclusion_compare(eleset_a, eleset_c), inclusion::unrelated);
+ typedef interval_map<int,int> IntervalMapT;
+ typedef split_interval_map<int,int> SplitIntervalMapT;
+ typedef interval_map<int,int> IntervalMapT;
+ typedef vector<pair<interval<int>,int> > IntervalVecT;
+
+ IntervalVecT ivec;
+ ivec.push_back(make_pair(interval<int>::rightopen(1,3),1));
+ ivec.push_back(make_pair(interval<int>::rightopen(2,4),1));
+
+ SplitIntervalMapT sim1, sim2;
+ sim1.insert(make_pair(interval<int>::rightopen(1,3),1));
+ sim1.insert(make_pair(interval<int>::rightopen(2,4),1));
+
+ IntervalMapT jim1, jim2;
+ std::copy(ivec.begin(), ivec.end(), std::inserter(jim2, jim2.end()));
+ cout << jim2 << endl;
}
Added: sandbox/itl/libs/itl/test/test_functions.hpp
==============================================================================
--- (empty file)
+++ sandbox/itl/libs/itl/test/test_functions.hpp 2009-10-03 06:34:24 EDT (Sat, 03 Oct 2009)
@@ -0,0 +1,61 @@
+/*-----------------------------------------------------------------------------+
+Copyright (c) 2008-2009: Joachim Faulhaber
++------------------------------------------------------------------------------+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENCE.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
++-----------------------------------------------------------------------------*/
+#ifndef BOOST_ITL_TEST_FUNCTIONS_H_JOFA_091003
+#define BOOST_ITL_TEST_FUNCTIONS_H_JOFA_091003
+
+#include <boost/itl/detail/notate.hpp>
+#include <boost/itl/type_traits/neutron.hpp>
+#include <boost/itl/functors.hpp>
+
+namespace boost{namespace itl
+{
+
+template <class T, class U, class Trt,
+ template<class T, class U,
+ class Traits = Trt,
+ ITL_COMPARE Compare = ITL_COMPARE_INSTANCE(std::less, U),
+ ITL_COMBINE Combine = ITL_COMBINE_INSTANCE(itl::inplace_plus, U),
+ ITL_SECTION Section = ITL_SECTION_INSTANCE(itl::inplace_et, U),
+ template<class,ITL_COMPARE>class Interval = interval,
+ ITL_ALLOC Alloc = std::allocator
+ >class IntervalMap,
+ class SequenceT
+>
+void itl_map_copy(const SequenceT& segments,
+ IntervalMap<T,U,Trt>& destination)
+{
+ //CL typedef Sequence<std::pair<itl::interval<T>,U> > SequenceT;
+ ITL_const_FORALL(SequenceT, segment_, segments)
+ destination.insert(*segment_);
+}
+
+
+template <class T, class U, class Trt,
+ template<class T, class U,
+ class Traits = Trt,
+ ITL_COMPARE Compare = ITL_COMPARE_INSTANCE(std::less, U),
+ ITL_COMBINE Combine = ITL_COMBINE_INSTANCE(itl::inplace_plus, U),
+ ITL_SECTION Section = ITL_SECTION_INSTANCE(itl::inplace_et, U),
+ template<class,ITL_COMPARE>class Interval = interval,
+ ITL_ALLOC Alloc = std::allocator
+ >class IntervalMap,
+ class SequenceT
+>
+void test_interval_map_copy_via_inserter(const SequenceT& segments)
+{
+ typedef IntervalMap<T,U,Trt> IntervalMapT;
+ IntervalMapT looped_copied_map, std_copied_map;
+ itl_map_copy(segments, looped_copied_map);
+ std::copy(segments.begin(), segments.end(), std::inserter(std_copied_map, std_copied_map.end()));
+ BOOST_CHECK_EQUAL( looped_copied_map, std_copied_map );
+}
+
+}} // namespace itl boost
+
+#endif // BOOST_ITL_TEST_FUNCTIONS_H_JOFA_091003
+
Modified: sandbox/itl/libs/itl/test/test_interval_map_/test_interval_map.cpp
==============================================================================
--- sandbox/itl/libs/itl/test/test_interval_map_/test_interval_map.cpp (original)
+++ sandbox/itl/libs/itl/test/test_interval_map_/test_interval_map.cpp 2009-10-03 06:34:24 EDT (Sat, 03 Oct 2009)
@@ -14,6 +14,7 @@
// interval instance types
#include "../test_type_lists.hpp"
#include "../test_value_maker.hpp"
+#include "../test_functions.hpp"
#include <boost/itl/separate_interval_set.hpp>
#include <boost/itl/split_interval_set.hpp>
@@ -26,8 +27,8 @@
using namespace boost::itl;
// -----------------------------------------------------------------------------
-// test_interval_set_shared are tests that should give identical results for all
-// interval_sets: interval_set, separate_interval_set and split_interval_set.
+// test_interval_map_shared are tests that should give identical results for all
+// interval_maps: interval_map and split_interval_map.
#include "../test_interval_map_shared.hpp"
#define INTERVAL_MAP interval_map
Modified: sandbox/itl/libs/itl/test/test_interval_map_cases.hpp
==============================================================================
--- sandbox/itl/libs/itl/test/test_interval_map_cases.hpp (original)
+++ sandbox/itl/libs/itl/test/test_interval_map_cases.hpp 2009-10-03 06:34:24 EDT (Sat, 03 Oct 2009)
@@ -71,5 +71,9 @@
(test_itl_interval_map_inclusion_compare_4_bicremental_types, T, bicremental_types)
{ interval_map_inclusion_compare_4_bicremental_types<T, int, partial_absorber, INTERVAL_MAP>();}
+BOOST_AUTO_TEST_CASE_TEMPLATE
+(test_itl_interval_map_std_copy_via_inserter_4_bicremental_types, T, bicremental_types)
+{ interval_map_std_copy_via_inserter_4_bicremental_types<T, int, partial_absorber, INTERVAL_MAP>();}
+
#endif // BOOST_ITL_TEST_INTERVAL_MAP_CASES_HPP_JOFA_090701
Modified: sandbox/itl/libs/itl/test/test_interval_map_shared.hpp
==============================================================================
--- sandbox/itl/libs/itl/test/test_interval_map_shared.hpp (original)
+++ sandbox/itl/libs/itl/test/test_interval_map_shared.hpp 2009-10-03 06:34:24 EDT (Sat, 03 Oct 2009)
@@ -1193,6 +1193,43 @@
}
+template <class T, class U, class Trt,
+ template<class T, class U,
+ class Traits = Trt,
+ ITL_COMPARE Compare = ITL_COMPARE_INSTANCE(std::less, U),
+ ITL_COMBINE Combine = ITL_COMBINE_INSTANCE(itl::inplace_plus, U),
+ ITL_SECTION Section = ITL_SECTION_INSTANCE(itl::inplace_et, U),
+ template<class,ITL_COMPARE>class Interval = interval,
+ ITL_ALLOC Alloc = std::allocator
+ >class IntervalMap
+ >
+void interval_map_std_copy_via_inserter_4_bicremental_types()
+{
+ typedef IntervalMap<T,U,Trt> IntervalMapT; //Nedded for the test value generator
+
+ // Check equality of copying using handcoded loop or std::copy via inserter.
+ typedef std::pair<interval<T>, U> SegmentT;
+ std::vector<SegmentT> seg_vec_a;
+
+ // For an empty sequence
+ test_interval_map_copy_via_inserter<T,U,Trt,IntervalMap,std::vector<SegmentT> >(seg_vec_a);
+
+ // For an singleton sequence
+ seg_vec_a.push_back(IDv(0,1,1));
+ test_interval_map_copy_via_inserter<T,U,Trt,IntervalMap,std::vector<SegmentT> >(seg_vec_a);
+
+ // Two separate segments
+ seg_vec_a.push_back(IDv(3,5,1));
+ test_interval_map_copy_via_inserter<T,U,Trt,IntervalMap,std::vector<SegmentT> >(seg_vec_a);
+
+ // Touching case
+ seg_vec_a.push_back(IDv(5,7,1));
+ test_interval_map_copy_via_inserter<T,U,Trt,IntervalMap,std::vector<SegmentT> >(seg_vec_a);
+
+ // Overlapping case
+ seg_vec_a.push_back(IDv(6,9,1));
+ test_interval_map_copy_via_inserter<T,U,Trt,IntervalMap,std::vector<SegmentT> >(seg_vec_a);
+}
#endif // __test_itl_interval_map_shared_h_JOFA_080920__
Modified: sandbox/itl/libs/itl/test/test_split_interval_map_/test_split_interval_map.cpp
==============================================================================
--- sandbox/itl/libs/itl/test/test_split_interval_map_/test_split_interval_map.cpp (original)
+++ sandbox/itl/libs/itl/test/test_split_interval_map_/test_split_interval_map.cpp 2009-10-03 06:34:24 EDT (Sat, 03 Oct 2009)
@@ -14,6 +14,7 @@
// interval instance types
#include "../test_type_lists.hpp"
#include "../test_value_maker.hpp"
+#include "../test_functions.hpp"
#include <boost/itl/separate_interval_set.hpp>
#include <boost/itl/split_interval_set.hpp>
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