From 3ec9a1859cfaf6f22c4ff0f28f5d8b1ed8dc123d Mon Sep 17 00:00:00 2001
From: Owen Arnold <owen.arnold@stfc.ac.uk>
Date: Wed, 1 Apr 2020 16:29:04 +0100
Subject: [PATCH] Sample operator== and operator!=

---
 Framework/API/inc/MantidAPI/Sample.h          |   3 +
 Framework/API/src/Sample.cpp                  |  32 +++++
 Framework/API/test/SampleTest.h               | 122 ++++++++++++++++++
 .../inc/MantidGeometry/Crystal/SpaceGroup.h   |   2 +
 Framework/Geometry/src/Crystal/SpaceGroup.cpp |   9 ++
 5 files changed, 168 insertions(+)

diff --git a/Framework/API/inc/MantidAPI/Sample.h b/Framework/API/inc/MantidAPI/Sample.h
index dc70c2391fa..7d5c79373ea 100644
--- a/Framework/API/inc/MantidAPI/Sample.h
+++ b/Framework/API/inc/MantidAPI/Sample.h
@@ -116,6 +116,9 @@ public:
   /// Delete the oriented lattice
   void clearOrientedLattice();
 
+  bool operator==(const Sample &other) const;
+  bool operator!=(const Sample &other) const;
+
 private:
   /// The sample name
   std::string m_name;
diff --git a/Framework/API/src/Sample.cpp b/Framework/API/src/Sample.cpp
index b26a1a04baf..a9c2b47be06 100644
--- a/Framework/API/src/Sample.cpp
+++ b/Framework/API/src/Sample.cpp
@@ -423,5 +423,37 @@ void Sample::clearOrientedLattice() {
     m_lattice.reset(nullptr);
   }
 }
+
+bool Sample::operator==(const Sample &other) const {
+  if (m_samples.size() != other.m_samples.size())
+    return false;
+  for (size_t i = 0; i < m_samples.size(); ++i) {
+    if (*m_samples[i] != *other.m_samples[i])
+      return false;
+  }
+  auto compare = [](const auto &a, const auto &b, auto call_on) {
+    // both null or both not null
+    if (bool(a) ^ bool(b))
+      return false;
+    if (a)
+      return call_on(a) == call_on(b);
+    else
+      return true;
+
+  };
+  return *m_lattice == *other.m_lattice && this->m_name == other.m_name &&
+         this->m_height == other.m_height && this->m_width == other.m_width &&
+         this->m_thick == other.m_thick && m_geom_id == other.m_geom_id &&
+         compare(m_environment, other.m_environment,
+                 [](const auto &x) { return x->name(); }) &&
+         compare(m_shape, other.m_shape,
+                 [](const auto &x) { return x->shape(); }) &&
+         compare(m_crystalStructure, other.m_crystalStructure,
+                 [](const auto &x) { return *(x->spaceGroup()); });
+}
+
+bool Sample::operator!=(const Sample &other) const {
+  return !this->operator==(other);
+}
 } // namespace API
 } // namespace Mantid
diff --git a/Framework/API/test/SampleTest.h b/Framework/API/test/SampleTest.h
index b4583c37056..5092ea50bc3 100644
--- a/Framework/API/test/SampleTest.h
+++ b/Framework/API/test/SampleTest.h
@@ -359,4 +359,126 @@ public:
 
     TS_ASSERT(loaded.getName().empty());
   }
+
+  void test_equal_when_sample_identical() {
+    Sample a;
+    Sample b;
+    TS_ASSERT_EQUALS(a, b);
+  }
+
+  void test_not_equal_when_sample_differs_in_extents() {
+    Sample a;
+    auto b = a;
+    a.setHeight(10);
+    TS_ASSERT_DIFFERS(a, b);
+    TS_ASSERT(!(a == b));
+    b = a;
+    a.setWidth(10);
+    TS_ASSERT_DIFFERS(a, b);
+    TS_ASSERT(!(a == b));
+    b = a;
+    a.setThickness(10);
+    TS_ASSERT_DIFFERS(a, b);
+    TS_ASSERT(!(a == b));
+  }
+
+  void test_not_equal_when_sample_differs_in_geom_id() {
+    Sample a;
+    auto b = a;
+    TS_ASSERT_EQUALS(a, b);
+    a.setGeometryFlag(1);
+    b.setGeometryFlag(2);
+    TS_ASSERT_DIFFERS(a, b);
+    TS_ASSERT(!(a == b));
+  }
+  void test_not_equal_when_sample_differs_in_name() {
+    Sample a;
+    auto b = a;
+    b.setName("something");
+    TS_ASSERT_DIFFERS(a, b);
+    TS_ASSERT(!(a == b));
+  }
+
+  void test_not_equal_when_sample_differs_in_environment() {
+    auto kit1 = std::make_unique<SampleEnvironment>(
+        "Env", boost::make_shared<const Container>(""));
+
+    auto kit2 = std::make_unique<SampleEnvironment>(
+        "Env2", boost::make_shared<const Container>(""));
+
+    // same as kit1
+    auto kit3 = std::make_unique<SampleEnvironment>(
+        kit1->name(), boost::make_shared<const Container>(""));
+
+    Sample a;
+    auto b = a;
+    b.setEnvironment(std::move(kit1));
+    // A has no environment
+    TS_ASSERT_DIFFERS(a, b);
+    TS_ASSERT(!(a == b));
+
+    // A has valid but different same environment
+    a.setEnvironment(std::move(kit2));
+    TS_ASSERT_DIFFERS(a, b);
+    TS_ASSERT(!(a == b));
+
+    // A has valid but different same environment
+    a.setEnvironment(std::move(kit3));
+    TS_ASSERT_EQUALS(a, b);
+    TS_ASSERT(!(a != b));
+  }
+
+  void test_not_equal_when_sample_differs_in_shape() {
+    IObject_sptr shape1 = ComponentCreationHelper::createCappedCylinder(
+        0.0127, 1.0, V3D(), V3D(0.0, 1.0, 0.0), "cyl");
+
+    IObject_sptr shape2 = ComponentCreationHelper::createCappedCylinder(
+        0.0137, 1.0, V3D(), V3D(0.0, 0.0, 0.0), "cyl");
+
+    Sample a;
+    auto b = a;
+    a.setShape(shape1);
+    // b has no shape
+    TS_ASSERT_DIFFERS(a, b);
+    TS_ASSERT(!(a == b));
+
+    // b has different shape
+    b.setShape(shape2);
+    TS_ASSERT_DIFFERS(a, b);
+    TS_ASSERT(!(a == b));
+
+    // b has same shape
+    b.setShape(IObject_sptr(shape1->clone()));
+    TS_ASSERT_EQUALS(a, b);
+    TS_ASSERT(!(a != b));
+  }
+
+  void test_not_equal_when_sample_differs_in_space_group() {
+    CrystalStructure structure1("3 4 5 90 90 90", "C m m m",
+                                "Fe 0.12 0.23 0.121");
+    // Same as above
+    CrystalStructure structure2("3 4 5 90 90 90", "C m m m",
+                                "Fe 0.12 0.23 0.121");
+    // Different
+    CrystalStructure structure3("5.431 5.431 5.431", "F d -3 m",
+                                "Si 0 0 0 1.0 0.02");
+
+    Sample a;
+    auto b = a;
+    // b has no structure
+    a.setCrystalStructure(structure1);
+    TS_ASSERT_DIFFERS(a, b);
+    TS_ASSERT(!(a == b));
+
+    // b has different structure
+    b.setCrystalStructure(structure3);
+    TS_ASSERT_DIFFERS(a, b);
+    TS_ASSERT(!(a == b));
+
+    // b has same structure
+    b = Sample{};
+    b.setCrystalStructure(structure2);
+    TS_ASSERT_EQUALS(a, b);
+    TS_ASSERT(!(a != b));
+  }
 };
diff --git a/Framework/Geometry/inc/MantidGeometry/Crystal/SpaceGroup.h b/Framework/Geometry/inc/MantidGeometry/Crystal/SpaceGroup.h
index f9bbe72f5ea..c978672a8a5 100644
--- a/Framework/Geometry/inc/MantidGeometry/Crystal/SpaceGroup.h
+++ b/Framework/Geometry/inc/MantidGeometry/Crystal/SpaceGroup.h
@@ -77,6 +77,8 @@ public:
 
   PointGroup_sptr getPointGroup() const;
   Group_const_sptr getSiteSymmetryGroup(const Kernel::V3D &position) const;
+  bool operator==(const SpaceGroup &other) const;
+  bool operator!=(const SpaceGroup &other) const;
 
 protected:
   size_t m_number;
diff --git a/Framework/Geometry/src/Crystal/SpaceGroup.cpp b/Framework/Geometry/src/Crystal/SpaceGroup.cpp
index a0407ae7aaf..5305ffbcaca 100644
--- a/Framework/Geometry/src/Crystal/SpaceGroup.cpp
+++ b/Framework/Geometry/src/Crystal/SpaceGroup.cpp
@@ -114,6 +114,15 @@ Group_const_sptr SpaceGroup::getSiteSymmetryGroup(const V3D &position) const {
   return GroupFactory::create<Group>(siteSymmetryOps);
 }
 
+bool SpaceGroup::operator==(const SpaceGroup &other) const {
+  return Group::operator==(other) && this->m_number == other.m_number &&
+         this->m_hmSymbol == other.hmSymbol();
+}
+
+bool SpaceGroup::operator!=(const SpaceGroup &other) const {
+  return !this->operator==(other);
+}
+
 std::ostream &operator<<(std::ostream &stream, const SpaceGroup &self) {
   stream << "Space group with Hermann-Mauguin symbol: " << self.hmSymbol();
   return stream;
-- 
GitLab