Add copy and move operations to density similarity
authorChristian Blau <cblau@gwdg.de>
Wed, 19 Jun 2019 11:35:18 +0000 (13:35 +0200)
committerEric Irrgang <ericirrgang@gmail.com>
Fri, 28 Jun 2019 11:12:16 +0000 (13:12 +0200)
Enable copying and moving for DensitySimilarityMeasure.

Change-Id: Ie4250f67ae42b5cea227b7c17b0a932b04a42a63

src/gromacs/math/densityfit.cpp
src/gromacs/math/densityfit.h
src/gromacs/math/tests/densityfit.cpp

index 1a928835fe5d9bff3c4496449b9504bb1d952e1a..ea210cf61942b7b783e705fd38e76eaf4b6f32b0 100644 (file)
@@ -64,6 +64,8 @@ class DensitySimilarityMeasureImpl
         virtual density gradient(density comparedDensity) = 0;
         //! \copydoc DensitySimilarityMeasure::gradient(density comparedDensity)
         virtual float similarity(density comparedDensity) = 0;
+        //! clone to allow copy operations
+        virtual std::unique_ptr<DensitySimilarityMeasureImpl> clone() = 0;
 };
 DensitySimilarityMeasureImpl::~DensitySimilarityMeasureImpl() = default;
 
@@ -81,8 +83,11 @@ class DensitySimilarityInnerProduct final : public DensitySimilarityMeasureImpl
         DensitySimilarityInnerProduct(density referenceDensity);
         //! The gradient for the inner product similarity measure is the reference density divided by the number of voxels
         density gradient(density comparedDensity) override;
+        //! Clone this
+        std::unique_ptr<DensitySimilarityMeasureImpl> clone() override;
         //! The similarity between reference density and compared density
         float similarity(density comparedDensity) override;
+    private:
         //! A view on the reference density
         const density referenceDensity_;
         //! Stores the gradient of the similarity measure in memory
@@ -125,6 +130,11 @@ DensitySimilarityMeasure::density DensitySimilarityInnerProduct::gradient(densit
     return gradient_.asConstView();
 }
 
+std::unique_ptr<DensitySimilarityMeasureImpl> DensitySimilarityInnerProduct::clone()
+{
+    return std::make_unique<DensitySimilarityInnerProduct>(referenceDensity_);
+}
+
 }   // namespace
 
 
@@ -154,4 +164,19 @@ float DensitySimilarityMeasure::similarity(density comparedDensity)
 
 DensitySimilarityMeasure::~DensitySimilarityMeasure()  = default;
 
+DensitySimilarityMeasure::DensitySimilarityMeasure(const DensitySimilarityMeasure &other)
+    : impl_(other.impl_->clone())
+{
+}
+
+DensitySimilarityMeasure &DensitySimilarityMeasure::operator=(const DensitySimilarityMeasure &other)
+{
+    impl_ = other.impl_->clone();
+    return *this;
+}
+
+DensitySimilarityMeasure::DensitySimilarityMeasure(DensitySimilarityMeasure &&) noexcept = default;
+
+DensitySimilarityMeasure &DensitySimilarityMeasure::operator=(DensitySimilarityMeasure &&) noexcept = default;
+
 } // namespace gmx
index c278b90e296a910f9f795f9ef1b5d2145237fc39..f0d6758652f248e07041c959ab8dcdeb0bf5e9fd 100644 (file)
@@ -86,6 +86,15 @@ class DensitySimilarityMeasure
          */
         DensitySimilarityMeasure(DensitySimilarityMeasureMethod method, density referenceDensity);
         ~DensitySimilarityMeasure();
+        //! Copy constructor
+        DensitySimilarityMeasure(const DensitySimilarityMeasure &other);
+        //! Copy assignment
+        DensitySimilarityMeasure &operator=(const DensitySimilarityMeasure &other);
+        //! Move constructor
+        DensitySimilarityMeasure(DensitySimilarityMeasure &&other) noexcept;
+        //! Move assignment
+        DensitySimilarityMeasure &operator=(DensitySimilarityMeasure &&other) noexcept;
+
         /*! \brief Derivative of the density similarity measure at all voxels.
          * \param[in] comparedDensity the variable density
          * \returns density similarity measure derivative
index 44e14f1a5b70637ab0f2062f922bf27a9dec38dd..0fcda3799460ffadd5a9e67adaf500868e6028b1 100644 (file)
@@ -118,6 +118,23 @@ TEST(DensitySimilarityTest, SimilarityThrowsIfDensitiesDontMatch)
     EXPECT_THROW(measure.similarity(comparedDensity.asConstView()), RangeError);
 }
 
+TEST(DensitySimilarityTest, CopiedMeasureInnerProductIsCorrect)
+{
+    MultiDimArray<std::vector<float>, dynamicExtents3D> referenceDensity(3, 3, 3);
+    std::iota(begin(referenceDensity), end(referenceDensity), 0);
+
+    DensitySimilarityMeasure measure(DensitySimilarityMeasureMethod::innerProduct, referenceDensity.asConstView());
+
+    DensitySimilarityMeasure copiedMeasure = measure;
+    MultiDimArray<std::vector<float>, dynamicExtents3D> comparedDensity(3, 3, 3);
+    std::iota(begin(comparedDensity), end(comparedDensity), -18);
+
+    // 0*(-18) + 1*(-17) .. + 26 * 8 / Number elements
+    const float expectedSimilarity = -117.0 / comparedDensity.asConstView().mapping().required_span_size();
+    EXPECT_FLOAT_EQ(expectedSimilarity, copiedMeasure.similarity(comparedDensity.asConstView()));
+}
+
+
 } // namespace test
 
 } // namespace gmx