From 71e77b8c879b5884cc19eb3229c377b34f74b91d Mon Sep 17 00:00:00 2001 From: dellaert Date: Sat, 6 Dec 2014 10:58:16 +0100 Subject: [PATCH 1/7] Compiles --- gtsam/geometry/tests/testCyclic.cpp | 61 ++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 14 deletions(-) diff --git a/gtsam/geometry/tests/testCyclic.cpp b/gtsam/geometry/tests/testCyclic.cpp index f15654b2e..bdf0c3e98 100644 --- a/gtsam/geometry/tests/testCyclic.cpp +++ b/gtsam/geometry/tests/testCyclic.cpp @@ -10,8 +10,8 @@ * -------------------------------------------------------------------------- */ /** - * @file testCyclic.cpp - * @brief Unit tests for cyclic group + * @file Cyclic.h + * @brief Cyclic group, can act on 2D vector spaces * @author Frank Dellaert **/ @@ -22,17 +22,21 @@ namespace gtsam { template class Cyclic { - size_t i_; + size_t i_; ///< we just use an unsigned int public: - static const Cyclic Identity = Cyclic(0); + /// Constructor Cyclic(size_t i) : i_(i) { } + /// Cast to size_t + operator size_t() const { + return i_; + } }; namespace traits { template struct identity > { - static const Cyclic value = Cyclic::Identity; + static const Cyclic value; typedef Cyclic value_type; }; template struct group_flavor > { @@ -42,6 +46,27 @@ template struct group_flavor > { } // \namespace gtsam +/** + * @file Cyclic.cpp + * @brief Cyclic group implementation + * @author Frank Dellaert + **/ + +namespace gtsam { + +namespace traits { +template +const Cyclic identity >::value = Cyclic(0); +} // \namespace traits + +} // \namespace gtsam + +/** + * @file testCyclic.cpp + * @brief Unit tests for cyclic group + * @author Frank Dellaert + **/ + //#include #include #include @@ -49,19 +74,27 @@ template struct group_flavor > { using namespace std; using namespace gtsam; -BOOST_CONCEPT_ASSERT((GroupConcept >)); +typedef Cyclic<6> G; -/* ************************************************************************* */ -TEST(Cyclic, Constructor) { -Cyclic<6> g(0); +//****************************************************************************** +TEST(Cyclic, Concept) { + EXPECT_LONGS_EQUAL(0,traits::identity::value); + //BOOST_CONCEPT_ASSERT((GroupConcept >)); // EXPECT(assert_equal(p1, p2)); // EXPECT_LONGS_EQUAL(2,offset2.size()); } -/* ************************************************************************* */ -int main() { -TestResult tr; -return TestRegistry::runAllTests(tr); +//****************************************************************************** +TEST(Cyclic, Constructor) { + G g(0); +// EXPECT(assert_equal(p1, p2)); +// EXPECT_LONGS_EQUAL(2,offset2.size()); } -/* ************************************************************************* */ + +//****************************************************************************** +int main() { + TestResult tr; + return TestRegistry::runAllTests(tr); +} +//****************************************************************************** From 07ef30039a5363fe43a617f9a36b18a4bab85d3f Mon Sep 17 00:00:00 2001 From: dellaert Date: Sat, 6 Dec 2014 11:17:54 +0100 Subject: [PATCH 2/7] structure_tag works --- gtsam/base/concepts.h | 55 +++++++++++++++++------------ gtsam/geometry/tests/testCyclic.cpp | 13 ++++--- 2 files changed, 38 insertions(+), 30 deletions(-) diff --git a/gtsam/base/concepts.h b/gtsam/base/concepts.h index 967a91707..393bb69b1 100644 --- a/gtsam/base/concepts.h +++ b/gtsam/base/concepts.h @@ -24,7 +24,7 @@ namespace traits { */ //@{ template -struct structure_category {}; // specializations should be derived from one of the following tags +struct structure_category; // specializations should be derived from one of the following tags //@} /** @@ -92,8 +92,8 @@ namespace traits { /** @name Group Traits */ //@{ -template struct identity {}; -template struct group_flavor {}; +template struct identity; +template struct group_flavor; //@} /** @name Group Flavor Tags */ @@ -104,41 +104,50 @@ struct multiplicative_group_tag {}; } // namespace traits +/** + * Group Concept + */ template -class GroupConcept { - public: - typedef G Group; - static const Group identity = traits::identity::value; +class Group { +public: - BOOST_CONCEPT_USAGE(GroupConcept) { - BOOST_STATIC_ASSERT(boost::is_base_of::type>::value ); - Group ip = inverse(p); - Group pq = compose(p, q); - Group d = between(p, q); - test = equal(p, q); - test2 = operator_usage(p, q, traits::group_flavor::type); + typedef typename traits::identity::value_type identity_value_type; + typedef typename traits::group_flavor::type group_flavor_tag; + typedef typename traits::structure_category::type structure_category_tag; + + BOOST_CONCEPT_USAGE(Group) { + e = traits::identity::value; +// BOOST_STATIC_ASSERT(boost::is_base_of::type>::value ); +// G ip = inverse(p); +// G pq = compose(p, q); +// G d = between(p, q); +// test = equal(p, q); +// test2 = operator_usage(p, q, traits::group_flavor::type); } - bool check_invariants(const Group& a, const Group& b) { - return (equal(compose(a, inverse(a)), identity)) + bool check_invariants(const G& a, const G& b) { + group_flavor_tag group_flavor; + return (equal(compose(a, inverse(a)), e)) && (equal(between(a, b), compose(inverse(a), b))) && (equal(compose(a, between(a, b)), b)) - && operator_usage(a, b, traits::group_flavor::type); + && operator_usage(a, b, group_flavor); } - private: - Group p,q; +private: + G p, q, e; bool test, test2; - bool operator_usage(const Group& a, const Group& b, const traits::multiplicative_group_tag&) { - return equal(compose(a, b), a*b); + bool operator_usage(const G& a, const G& b, + traits::multiplicative_group_tag) { + return equal(compose(a, b), a * b); } - bool operator_usage(const Group& a, const Group& b, const traits::additive_group_tag&) { - return equal(compose(a, b), a+b); + bool operator_usage(const G& a, const G& b, traits::additive_group_tag) { + return equal(compose(a, b), a + b); } }; + /* template class LieGroupConcept : public GroupConcept, public ManifoldConcept { diff --git a/gtsam/geometry/tests/testCyclic.cpp b/gtsam/geometry/tests/testCyclic.cpp index bdf0c3e98..8ea678a0f 100644 --- a/gtsam/geometry/tests/testCyclic.cpp +++ b/gtsam/geometry/tests/testCyclic.cpp @@ -11,7 +11,7 @@ /** * @file Cyclic.h - * @brief Cyclic group, can act on 2D vector spaces + * @brief Cyclic group, i.e., the integers modulo N * @author Frank Dellaert **/ @@ -35,6 +35,9 @@ public: }; namespace traits { +template struct structure_category > { + typedef group_tag type; +}; template struct identity > { static const Cyclic value; typedef Cyclic value_type; @@ -74,21 +77,17 @@ const Cyclic identity >::value = Cyclic(0); using namespace std; using namespace gtsam; -typedef Cyclic<6> G; +typedef Cyclic<6> G; // Let's use the cyclic group of order 6 //****************************************************************************** TEST(Cyclic, Concept) { EXPECT_LONGS_EQUAL(0,traits::identity::value); - //BOOST_CONCEPT_ASSERT((GroupConcept >)); -// EXPECT(assert_equal(p1, p2)); -// EXPECT_LONGS_EQUAL(2,offset2.size()); + BOOST_CONCEPT_ASSERT((Group)); } //****************************************************************************** TEST(Cyclic, Constructor) { G g(0); -// EXPECT(assert_equal(p1, p2)); -// EXPECT_LONGS_EQUAL(2,offset2.size()); } //****************************************************************************** From ddeb7649121942ab803ce40cba3cf2ee3b17fedf Mon Sep 17 00:00:00 2001 From: dellaert Date: Sat, 6 Dec 2014 11:37:14 +0100 Subject: [PATCH 3/7] group::traits, and group::compose --- gtsam/base/concepts.h | 172 +++++++++++++++------------- gtsam/geometry/tests/testCyclic.cpp | 19 ++- 2 files changed, 109 insertions(+), 82 deletions(-) diff --git a/gtsam/base/concepts.h b/gtsam/base/concepts.h index 393bb69b1..6910518da 100644 --- a/gtsam/base/concepts.h +++ b/gtsam/base/concepts.h @@ -23,8 +23,9 @@ namespace traits { * @brief Associate a unique tag with each of the main GTSAM concepts */ //@{ -template -struct structure_category; // specializations should be derived from one of the following tags +template +struct structure_category; +// specializations should be derived from one of the following tags //@} /** @@ -32,97 +33,111 @@ struct structure_category; // specializations should be derived from one of the * @brief Possible values for traits::structure_category::type */ //@{ -struct manifold_tag {}; -struct group_tag {}; -struct lie_group_tag : public manifold_tag, public group_tag {}; -struct vector_space_tag : public lie_group_tag {}; +struct manifold_tag { +}; +struct group_tag { +}; +struct lie_group_tag: public manifold_tag, public group_tag { +}; +struct vector_space_tag: public lie_group_tag { +}; //@} -} // namespace traits +}// namespace traits namespace traits { /** @name Manifold Traits */ //@{ -template struct TangentVector; -template struct DefaultChart; +template struct TangentVector; +template struct DefaultChart; //@} -} // namespace traits +}// namespace traits /* -template -class ManifoldConcept { + template + class ManifoldConcept { public: - typedef T Manifold; - typedef typename traits::TangentVector::type TangentVector; - typedef typename traits::DefaultChart::type DefaultChart; - static const size_t dim = traits::dimension::value; + typedef T Manifold; + typedef typename traits::TangentVector::type TangentVector; + typedef typename traits::DefaultChart::type DefaultChart; + static const size_t dim = traits::dimension::value; - BOOST_CONCEPT_USAGE(ManifoldConcept) { - BOOST_STATIC_ASSERT(boost::is_base_of >); - BOOST_STATIC_ASSERT(TangentVector::SizeAtCompileTime == dim); - // no direct usage for manifold since most usage is through a chart - } + BOOST_CONCEPT_USAGE(ManifoldConcept) { + BOOST_STATIC_ASSERT(boost::is_base_of >); + BOOST_STATIC_ASSERT(TangentVector::SizeAtCompileTime == dim); + // no direct usage for manifold since most usage is through a chart + } private: - Manifold p; - TangentVector v; -}; + Manifold p; + TangentVector v; + }; -template -class ChartConcept { + template + class ChartConcept { public: - typedef C Chart; - typedef typename traits::Manifold::type Manifold; - typedef typename traits::TangentVector::type TangentVector; + typedef C Chart; + typedef typename traits::Manifold::type Manifold; + typedef typename traits::TangentVector::type TangentVector; - BOOST_CONCEPT_USAGE(ChartConcept) { - v = Chart::local(p,q); // returns local coordinates of q w.r.t. origin p - q = Chart::retract(p,v); // returns retracted update of p with v - } + BOOST_CONCEPT_USAGE(ChartConcept) { + v = Chart::local(p,q); // returns local coordinates of q w.r.t. origin p + q = Chart::retract(p,v); // returns retracted update of p with v + } private: - Manifold p,q; - TangentVector v; + Manifold p,q; + TangentVector v; -}; -*/ + }; + */ + +namespace group { + +template +G compose(const G&g, const G& h); namespace traits { /** @name Group Traits */ //@{ -template struct identity; -template struct group_flavor; +template struct identity; +template struct flavor; //@} /** @name Group Flavor Tags */ //@{ -struct additive_group_tag {}; -struct multiplicative_group_tag {}; +struct additive_tag { +}; +struct multiplicative_tag { +}; //@} -} // namespace traits +} // \ namespace traits +} // \ namespace group /** * Group Concept */ -template +template class Group { public: - typedef typename traits::identity::value_type identity_value_type; - typedef typename traits::group_flavor::type group_flavor_tag; typedef typename traits::structure_category::type structure_category_tag; + typedef typename group::traits::identity::value_type identity_value_type; + typedef typename group::traits::flavor::type group_flavor_tag; BOOST_CONCEPT_USAGE(Group) { - e = traits::identity::value; -// BOOST_STATIC_ASSERT(boost::is_base_of::type>::value ); + using group::compose; + BOOST_STATIC_ASSERT( + boost::is_base_of::value); + e = group::traits::identity::value; + pq = compose(p, q); // G ip = inverse(p); -// G pq = compose(p, q); // G d = between(p, q); // test = equal(p, q); -// test2 = operator_usage(p, q, traits::group_flavor::type); +// test2 = operator_usage(p, q, group::traits::_flavor::type); } bool check_invariants(const G& a, const G& b) { @@ -134,54 +149,53 @@ public: } private: - G p, q, e; + G e, p, q, pq, ip, d; bool test, test2; bool operator_usage(const G& a, const G& b, - traits::multiplicative_group_tag) { + group::traits::multiplicative_tag) { return equal(compose(a, b), a * b); } - bool operator_usage(const G& a, const G& b, traits::additive_group_tag) { + bool operator_usage(const G& a, const G& b, group::traits::additive_tag) { return equal(compose(a, b), a + b); } }; /* -template -class LieGroupConcept : public GroupConcept, public ManifoldConcept { + template + class LieGroupConcept : public GroupConcept, public ManifoldConcept { - BOOST_CONCEPT_USAGE(LieGroupConcept) { - BOOST_STATIC_ASSERT(boost::is_base_of >); - } -}; + BOOST_CONCEPT_USAGE(LieGroupConcept) { + BOOST_STATIC_ASSERT(boost::is_base_of >); + } + }; -template -class VectorSpaceConcept : public LieGroupConcept { - typedef typename traits::DefaultChart::type Chart; - typedef typename GroupConcept::identity identity; + template + class VectorSpaceConcept : public LieGroupConcept { + typedef typename traits::DefaultChart::type Chart; + typedef typename GroupConcept::identity identity; - BOOST_CONCEPT_USAGE(VectorSpaceConcept) { - BOOST_STATIC_ASSERT(boost::is_base_of >); - r = p+q; - r = -p; - r = p-q; - } + BOOST_CONCEPT_USAGE(VectorSpaceConcept) { + BOOST_STATIC_ASSERT(boost::is_base_of >); + r = p+q; + r = -p; + r = p-q; + } - bool check_invariants(const V& a, const V& b) { - return equal(compose(a, b), a+b) - && equal(inverse(a), -a) - && equal(between(a, b), b-a) - && equal(Chart::retract(a, b), a+b) - && equal(Chart::local(a, b), b-a); - } + bool check_invariants(const V& a, const V& b) { + return equal(compose(a, b), a+b) + && equal(inverse(a), -a) + && equal(between(a, b), b-a) + && equal(Chart::retract(a, b), a+b) + && equal(Chart::local(a, b), b-a); + } private: - V p,q,r; -}; -*/ + V p,q,r; + }; + */ } // namespace gtsam - diff --git a/gtsam/geometry/tests/testCyclic.cpp b/gtsam/geometry/tests/testCyclic.cpp index 8ea678a0f..7bc19a2b7 100644 --- a/gtsam/geometry/tests/testCyclic.cpp +++ b/gtsam/geometry/tests/testCyclic.cpp @@ -35,17 +35,28 @@ public: }; namespace traits { +/// Define Cyclic to be a model of the Group concept template struct structure_category > { typedef group_tag type; }; +} // \namespace traits + +namespace group { +template +Cyclic compose(const Cyclic&g, const Cyclic& h); + +namespace traits { +/// Define the trait that specifies Cyclic's identity element template struct identity > { static const Cyclic value; typedef Cyclic value_type; }; -template struct group_flavor > { - typedef additive_group_tag type; +/// Define the trait that asserts Cyclic is an additive group +template struct flavor > { + typedef additive_tag type; }; } // \namespace traits +} // \namespace group } // \namespace gtsam @@ -57,10 +68,12 @@ template struct group_flavor > { namespace gtsam { +namespace group { namespace traits { template const Cyclic identity >::value = Cyclic(0); } // \namespace traits +} // \namespace group } // \namespace gtsam @@ -81,7 +94,7 @@ typedef Cyclic<6> G; // Let's use the cyclic group of order 6 //****************************************************************************** TEST(Cyclic, Concept) { - EXPECT_LONGS_EQUAL(0,traits::identity::value); + EXPECT_LONGS_EQUAL(0, group::traits::identity::value); BOOST_CONCEPT_ASSERT((Group)); } From 5407232e367a2d25a9cdcbcd1fa2308e6ce418d4 Mon Sep 17 00:00:00 2001 From: dellaert Date: Sat, 6 Dec 2014 11:51:44 +0100 Subject: [PATCH 4/7] between and inverse, as well as tag dispatching --- gtsam/base/concepts.h | 34 +++++++++++++++++------------ gtsam/geometry/tests/testCyclic.cpp | 6 +++++ 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/gtsam/base/concepts.h b/gtsam/base/concepts.h index 6910518da..d3f2fe87c 100644 --- a/gtsam/base/concepts.h +++ b/gtsam/base/concepts.h @@ -95,8 +95,12 @@ template struct DefaultChart; namespace group { -template -G compose(const G&g, const G& h); +/** @name Free functions any Group needs to define */ +//@{ +template G compose(const G&g, const G& h); +template G between(const G&g, const G& h); +template G inverse(const G&g); +//@} namespace traits { @@ -126,39 +130,41 @@ public: typedef typename traits::structure_category::type structure_category_tag; typedef typename group::traits::identity::value_type identity_value_type; - typedef typename group::traits::flavor::type group_flavor_tag; + typedef typename group::traits::flavor::type flavor_tag; BOOST_CONCEPT_USAGE(Group) { using group::compose; + using group::between; + using group::inverse; BOOST_STATIC_ASSERT( boost::is_base_of::value); e = group::traits::identity::value; - pq = compose(p, q); -// G ip = inverse(p); -// G d = between(p, q); -// test = equal(p, q); -// test2 = operator_usage(p, q, group::traits::_flavor::type); + d = compose(g, h); + d = between(g, h); + ig = inverse(g); + test = operator_usage(g, h, flavor); +// test2 = equal(g, h); } bool check_invariants(const G& a, const G& b) { - group_flavor_tag group_flavor; return (equal(compose(a, inverse(a)), e)) && (equal(between(a, b), compose(inverse(a), b))) && (equal(compose(a, between(a, b)), b)) - && operator_usage(a, b, group_flavor); + && operator_usage(a, b, flavor); } private: - G e, p, q, pq, ip, d; + flavor_tag flavor; + G e, g, h, gh, ig, d; bool test, test2; bool operator_usage(const G& a, const G& b, group::traits::multiplicative_tag) { - return equal(compose(a, b), a * b); + return group::compose(a, b) == a * b; } bool operator_usage(const G& a, const G& b, group::traits::additive_tag) { - return equal(compose(a, b), a + b); + return group::compose(a, b) == a + b; } }; @@ -193,7 +199,7 @@ private: } private: - V p,q,r; + V g,q,r; }; */ diff --git a/gtsam/geometry/tests/testCyclic.cpp b/gtsam/geometry/tests/testCyclic.cpp index 7bc19a2b7..882d8fb1c 100644 --- a/gtsam/geometry/tests/testCyclic.cpp +++ b/gtsam/geometry/tests/testCyclic.cpp @@ -45,6 +45,12 @@ namespace group { template Cyclic compose(const Cyclic&g, const Cyclic& h); +template +Cyclic between(const Cyclic&g, const Cyclic& h); + +template +Cyclic inverse(const Cyclic&g); + namespace traits { /// Define the trait that specifies Cyclic's identity element template struct identity > { From 6c2b28aa8b2a1f1b268fe15802108b9a3009591d Mon Sep 17 00:00:00 2001 From: dellaert Date: Sat, 6 Dec 2014 12:50:40 +0100 Subject: [PATCH 5/7] between tested --- gtsam/base/concepts.h | 18 +++++++------ gtsam/geometry/tests/testCyclic.cpp | 39 +++++++++++++++++++++++++---- 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/gtsam/base/concepts.h b/gtsam/base/concepts.h index d3f2fe87c..9011c759b 100644 --- a/gtsam/base/concepts.h +++ b/gtsam/base/concepts.h @@ -143,15 +143,19 @@ public: d = between(g, h); ig = inverse(g); test = operator_usage(g, h, flavor); -// test2 = equal(g, h); } - bool check_invariants(const G& a, const G& b) { - return (equal(compose(a, inverse(a)), e)) - && (equal(between(a, b), compose(inverse(a), b))) - && (equal(compose(a, between(a, b)), b)) - && operator_usage(a, b, flavor); - } +// TODO: these all require default constructors :-( +// Also, requires equal which is not required of a group +// Group():e(group::traits::identity::value) { +// } +// +// bool check_invariants(const G& a, const G& b) { +// return (equal(compose(a, inverse(a)), e)) +// && (equal(between(a, b), compose(inverse(a), b))) +// && (equal(compose(a, between(a, b)), b)) +// && operator_usage(a, b, flavor); +// } private: flavor_tag flavor; diff --git a/gtsam/geometry/tests/testCyclic.cpp b/gtsam/geometry/tests/testCyclic.cpp index 882d8fb1c..f46b85511 100644 --- a/gtsam/geometry/tests/testCyclic.cpp +++ b/gtsam/geometry/tests/testCyclic.cpp @@ -32,6 +32,10 @@ public: operator size_t() const { return i_; } + /// Addition modulo N + Cyclic operator+(const Cyclic& h) const { + return (i_+h.i_) % N; + } }; namespace traits { @@ -42,14 +46,21 @@ template struct structure_category > { } // \namespace traits namespace group { -template -Cyclic compose(const Cyclic&g, const Cyclic& h); template -Cyclic between(const Cyclic&g, const Cyclic& h); +Cyclic compose(const Cyclic&g, const Cyclic& h) { + return g + h; +} template -Cyclic inverse(const Cyclic&g); +Cyclic between(const Cyclic&g, const Cyclic& h) { + return h - g; +} + +template +Cyclic inverse(const Cyclic&g) { + return -g; +} namespace traits { /// Define the trait that specifies Cyclic's identity element @@ -100,8 +111,10 @@ typedef Cyclic<6> G; // Let's use the cyclic group of order 6 //****************************************************************************** TEST(Cyclic, Concept) { - EXPECT_LONGS_EQUAL(0, group::traits::identity::value); BOOST_CONCEPT_ASSERT((Group)); + EXPECT_LONGS_EQUAL(0, group::traits::identity::value); + G g(2), h(3); + // EXPECT(Group().check_invariants(g,h)) } //****************************************************************************** @@ -109,6 +122,22 @@ TEST(Cyclic, Constructor) { G g(0); } +//****************************************************************************** +TEST(Cyclic, Compose) { + G e(0), g(2), h(3); + EXPECT_LONGS_EQUAL(5, group::compose(g,h)); + EXPECT_LONGS_EQUAL(0, group::compose(h,h)); + EXPECT_LONGS_EQUAL(3, group::compose(h,e)); +} + +//****************************************************************************** +TEST(Cyclic, Between) { + G g(2), h(3); + EXPECT_LONGS_EQUAL(1, group::between(g,h)); + EXPECT_LONGS_EQUAL(0, group::between(g,g)); + EXPECT_LONGS_EQUAL(0, group::between(h,h)); +} + //****************************************************************************** int main() { TestResult tr; From 4d2a0aefc103070e3cc76af3fe27129dad680241 Mon Sep 17 00:00:00 2001 From: dellaert Date: Sat, 6 Dec 2014 12:59:35 +0100 Subject: [PATCH 6/7] Group checks out ! --- gtsam/geometry/tests/testCyclic.cpp | 52 ++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/gtsam/geometry/tests/testCyclic.cpp b/gtsam/geometry/tests/testCyclic.cpp index f46b85511..61c700c8a 100644 --- a/gtsam/geometry/tests/testCyclic.cpp +++ b/gtsam/geometry/tests/testCyclic.cpp @@ -36,6 +36,14 @@ public: Cyclic operator+(const Cyclic& h) const { return (i_+h.i_) % N; } + /// Subtraction modulo N + Cyclic operator-(const Cyclic& h) const { + return (N+i_-h.i_) % N; + } + /// Inverse + Cyclic operator-() const { + return (N-i_) % N; + } }; namespace traits { @@ -124,18 +132,46 @@ TEST(Cyclic, Constructor) { //****************************************************************************** TEST(Cyclic, Compose) { - G e(0), g(2), h(3); - EXPECT_LONGS_EQUAL(5, group::compose(g,h)); - EXPECT_LONGS_EQUAL(0, group::compose(h,h)); - EXPECT_LONGS_EQUAL(3, group::compose(h,e)); + EXPECT_LONGS_EQUAL(0, group::compose(G(0),G(0))); + EXPECT_LONGS_EQUAL(1, group::compose(G(0),G(1))); + EXPECT_LONGS_EQUAL(2, group::compose(G(0),G(2))); + EXPECT_LONGS_EQUAL(3, group::compose(G(0),G(3))); + EXPECT_LONGS_EQUAL(4, group::compose(G(0),G(4))); + EXPECT_LONGS_EQUAL(5, group::compose(G(0),G(5))); + + EXPECT_LONGS_EQUAL(2, group::compose(G(2),G(0))); + EXPECT_LONGS_EQUAL(3, group::compose(G(2),G(1))); + EXPECT_LONGS_EQUAL(4, group::compose(G(2),G(2))); + EXPECT_LONGS_EQUAL(5, group::compose(G(2),G(3))); + EXPECT_LONGS_EQUAL(0, group::compose(G(2),G(4))); + EXPECT_LONGS_EQUAL(1, group::compose(G(2),G(5))); } //****************************************************************************** TEST(Cyclic, Between) { - G g(2), h(3); - EXPECT_LONGS_EQUAL(1, group::between(g,h)); - EXPECT_LONGS_EQUAL(0, group::between(g,g)); - EXPECT_LONGS_EQUAL(0, group::between(h,h)); + EXPECT_LONGS_EQUAL(0, group::between(G(0),G(0))); + EXPECT_LONGS_EQUAL(1, group::between(G(0),G(1))); + EXPECT_LONGS_EQUAL(2, group::between(G(0),G(2))); + EXPECT_LONGS_EQUAL(3, group::between(G(0),G(3))); + EXPECT_LONGS_EQUAL(4, group::between(G(0),G(4))); + EXPECT_LONGS_EQUAL(5, group::between(G(0),G(5))); + + EXPECT_LONGS_EQUAL(4, group::between(G(2),G(0))); + EXPECT_LONGS_EQUAL(5, group::between(G(2),G(1))); + EXPECT_LONGS_EQUAL(0, group::between(G(2),G(2))); + EXPECT_LONGS_EQUAL(1, group::between(G(2),G(3))); + EXPECT_LONGS_EQUAL(2, group::between(G(2),G(4))); + EXPECT_LONGS_EQUAL(3, group::between(G(2),G(5))); +} + +//****************************************************************************** +TEST(Cyclic, Ivnverse) { + EXPECT_LONGS_EQUAL(0, group::inverse(G(0))); + EXPECT_LONGS_EQUAL(5, group::inverse(G(1))); + EXPECT_LONGS_EQUAL(4, group::inverse(G(2))); + EXPECT_LONGS_EQUAL(3, group::inverse(G(3))); + EXPECT_LONGS_EQUAL(2, group::inverse(G(4))); + EXPECT_LONGS_EQUAL(1, group::inverse(G(5))); } //****************************************************************************** From 614bfeb9d39a375a5a16904214772b9cf15684b7 Mon Sep 17 00:00:00 2001 From: dellaert Date: Sat, 6 Dec 2014 13:11:56 +0100 Subject: [PATCH 7/7] Moved to headers --- gtsam/geometry/Cyclic.cpp | 27 ++++++++ gtsam/geometry/Cyclic.h | 89 +++++++++++++++++++++++++++ gtsam/geometry/tests/testCyclic.cpp | 95 +---------------------------- 3 files changed, 117 insertions(+), 94 deletions(-) create mode 100644 gtsam/geometry/Cyclic.cpp create mode 100644 gtsam/geometry/Cyclic.h diff --git a/gtsam/geometry/Cyclic.cpp b/gtsam/geometry/Cyclic.cpp new file mode 100644 index 000000000..2b14ec6ba --- /dev/null +++ b/gtsam/geometry/Cyclic.cpp @@ -0,0 +1,27 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file Cyclic.cpp + * @brief Cyclic group implementation + * @author Frank Dellaert + **/ + +#include + +namespace gtsam { +namespace group { +namespace traits { + +} // \namespace traits +} // \namespace group +} // \namespace gtsam + diff --git a/gtsam/geometry/Cyclic.h b/gtsam/geometry/Cyclic.h new file mode 100644 index 000000000..85602d12d --- /dev/null +++ b/gtsam/geometry/Cyclic.h @@ -0,0 +1,89 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file Cyclic.h + * @brief Cyclic group, i.e., the integers modulo N + * @author Frank Dellaert + **/ + +#include +#include + +namespace gtsam { + +template +class Cyclic { + size_t i_; ///< we just use an unsigned int +public: + /// Constructor + Cyclic(size_t i) : + i_(i) { + } + /// Cast to size_t + operator size_t() const { + return i_; + } + /// Addition modulo N + Cyclic operator+(const Cyclic& h) const { + return (i_ + h.i_) % N; + } + /// Subtraction modulo N + Cyclic operator-(const Cyclic& h) const { + return (N + i_ - h.i_) % N; + } + /// Inverse + Cyclic operator-() const { + return (N - i_) % N; + } +}; + +namespace traits { +/// Define Cyclic to be a model of the Group concept +template struct structure_category > { + typedef group_tag type; +}; +} // \namespace gtsam::traits + +namespace group { + +template +Cyclic compose(const Cyclic&g, const Cyclic& h) { + return g + h; +} + +template +Cyclic between(const Cyclic&g, const Cyclic& h) { + return h - g; +} + +template +Cyclic inverse(const Cyclic&g) { + return -g; +} + +namespace traits { + +/// Define the trait that specifies Cyclic's identity element +template struct identity > { + static const Cyclic value = Cyclic(0); + typedef Cyclic value_type; +}; + +/// Define the trait that asserts Cyclic is an additive group +template struct flavor > { + typedef additive_tag type; +}; + +} // \namespace gtsam::group::traits +} // \namespace gtsam::group +} // \namespace gtsam + diff --git a/gtsam/geometry/tests/testCyclic.cpp b/gtsam/geometry/tests/testCyclic.cpp index 61c700c8a..00ea2c853 100644 --- a/gtsam/geometry/tests/testCyclic.cpp +++ b/gtsam/geometry/tests/testCyclic.cpp @@ -9,106 +9,13 @@ * -------------------------------------------------------------------------- */ -/** - * @file Cyclic.h - * @brief Cyclic group, i.e., the integers modulo N - * @author Frank Dellaert - **/ - -#include -#include - -namespace gtsam { - -template -class Cyclic { - size_t i_; ///< we just use an unsigned int -public: - /// Constructor - Cyclic(size_t i) : - i_(i) { - } - /// Cast to size_t - operator size_t() const { - return i_; - } - /// Addition modulo N - Cyclic operator+(const Cyclic& h) const { - return (i_+h.i_) % N; - } - /// Subtraction modulo N - Cyclic operator-(const Cyclic& h) const { - return (N+i_-h.i_) % N; - } - /// Inverse - Cyclic operator-() const { - return (N-i_) % N; - } -}; - -namespace traits { -/// Define Cyclic to be a model of the Group concept -template struct structure_category > { - typedef group_tag type; -}; -} // \namespace traits - -namespace group { - -template -Cyclic compose(const Cyclic&g, const Cyclic& h) { - return g + h; -} - -template -Cyclic between(const Cyclic&g, const Cyclic& h) { - return h - g; -} - -template -Cyclic inverse(const Cyclic&g) { - return -g; -} - -namespace traits { -/// Define the trait that specifies Cyclic's identity element -template struct identity > { - static const Cyclic value; - typedef Cyclic value_type; -}; -/// Define the trait that asserts Cyclic is an additive group -template struct flavor > { - typedef additive_tag type; -}; -} // \namespace traits -} // \namespace group - -} // \namespace gtsam - -/** - * @file Cyclic.cpp - * @brief Cyclic group implementation - * @author Frank Dellaert - **/ - -namespace gtsam { - -namespace group { -namespace traits { -template -const Cyclic identity >::value = Cyclic(0); -} // \namespace traits -} // \namespace group - -} // \namespace gtsam - /** * @file testCyclic.cpp * @brief Unit tests for cyclic group * @author Frank Dellaert **/ -//#include +#include #include #include