diff --git a/gtsam/geometry/Cyclic.h b/gtsam/geometry/Cyclic.h index aded063e7..94d302d5b 100644 --- a/gtsam/geometry/Cyclic.h +++ b/gtsam/geometry/Cyclic.h @@ -20,21 +20,39 @@ namespace gtsam { -/// Additive Group +/// Additive Group, using CRTP template -class AdditiveGroup { - +struct AdditiveGroup { + static Derived Identity() { + return Derived::Identity(); + } + Derived const * derived() const { + return static_cast(this); + } + Derived operator+(const AdditiveGroup& h) const { + return derived()->operator+(*h.derived()); + } + Derived operator-(const AdditiveGroup& h) const { + return derived()->operator-(*h.derived()); + } + Derived operator-() const { + return derived()->operator-(); + } }; /// Cyclic group of order N template -class Cyclic : AdditiveGroup > { +class Cyclic : public AdditiveGroup > { size_t i_; ///< we just use an unsigned int public: /// Constructor Cyclic(size_t i) : i_(i) { } + // Idenity element + static Cyclic Identity() { + return Cyclic(0); + } /// Cast to size_t operator size_t() const { return i_; @@ -64,8 +82,9 @@ public: }; namespace traits { -/// Define Cyclic to be a model of the Group concept -template struct structure_category > { +/// Define any additive group to be at least a model of the Group concept +template +struct structure_category > { typedef group_tag type; }; } // \namespace gtsam::traits @@ -73,30 +92,30 @@ template struct structure_category > { namespace group { template -AdditiveGroup compose(const AdditiveGroup&g, const AdditiveGroup& h) { +G compose(const AdditiveGroup&g, const AdditiveGroup& h) { return g + h; } template -AdditiveGroup between(const AdditiveGroup&g, const AdditiveGroup& h) { +G between(const AdditiveGroup&g, const AdditiveGroup& h) { return h - g; } template -AdditiveGroup inverse(const AdditiveGroup&g) { +G inverse(const AdditiveGroup&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; +template struct identity > { + static const G value; + typedef G value_type; }; -template -const Cyclic identity >::value = Cyclic(0); +template +const G identity >::value = AdditiveGroup::Identity(); /// Define the trait that asserts AdditiveGroup is an additive group template struct flavor > { diff --git a/gtsam/geometry/tests/testCyclic.cpp b/gtsam/geometry/tests/testCyclic.cpp index 1a30beb1c..95ed1b5b9 100644 --- a/gtsam/geometry/tests/testCyclic.cpp +++ b/gtsam/geometry/tests/testCyclic.cpp @@ -27,7 +27,7 @@ typedef Cyclic<6> G; // Let's use the cyclic group of order 6 //****************************************************************************** TEST(Cyclic, Concept) { // BOOST_CONCEPT_ASSERT((IsGroup)); - BOOST_CONCEPT_ASSERT((AdditiveGroup)); +// BOOST_CONCEPT_ASSERT((IsGroup >)); EXPECT_LONGS_EQUAL(0, group::traits::identity::value); G g(2), h(3); // EXPECT(Group().check_invariants(g,h))