From dee5092fa04e628c1a64361c645a5c4e9e4c3062 Mon Sep 17 00:00:00 2001
From: Randolf Beerwerth <r.beerwerth@fz-juelich.de>
Date: Mon, 23 Mar 2020 09:48:32 +0100
Subject: [PATCH] Introduce strategy pointers into IFresnelMap and
 SpecularComputationTerm

---
 Core/Computation/ProcessedSample.cpp         |  6 ++++--
 Core/Computation/SpecularComputation.cpp     |  6 ++++--
 Core/Computation/SpecularComputationTerm.cpp | 10 +++++++---
 Core/Computation/SpecularComputationTerm.h   | 13 ++++++++++---
 Core/Multilayer/IFresnelMap.cpp              |  3 ++-
 Core/Multilayer/IFresnelMap.h                |  5 ++++-
 Core/Multilayer/MatrixFresnelMap.cpp         |  6 +++---
 Core/Multilayer/MatrixFresnelMap.h           |  2 +-
 Core/Multilayer/ScalarFresnelMap.cpp         | 13 ++++++-------
 Core/Multilayer/ScalarFresnelMap.h           |  8 ++++----
 10 files changed, 45 insertions(+), 27 deletions(-)

diff --git a/Core/Computation/ProcessedSample.cpp b/Core/Computation/ProcessedSample.cpp
index c2dedc087a9..1cfb44024b5 100644
--- a/Core/Computation/ProcessedSample.cpp
+++ b/Core/Computation/ProcessedSample.cpp
@@ -24,6 +24,8 @@
 #include "ScalarFresnelMap.h"
 #include "SimulationOptions.h"
 #include "Slice.h"
+#include "SpecularScalarStrategy.h"
+#include "SpecularMagneticStrategy.h"
 
 namespace
 {
@@ -282,9 +284,9 @@ std::unique_ptr<IFresnelMap> CreateFresnelMap(const std::vector<Slice>& slices,
 {
     std::unique_ptr<IFresnelMap> P_result;
     if (ContainsMagneticSlice(slices))
-        P_result.reset(new MatrixFresnelMap());
+        P_result.reset(new MatrixFresnelMap(std::make_unique<SpecularMagneticStrategy>()));
     else
-        P_result.reset(new ScalarFresnelMap());
+        P_result.reset(new ScalarFresnelMap(std::make_unique<SpecularScalarStrategy>()));
     if (options.isIntegrate())
         P_result->disableCaching();
     return P_result;
diff --git a/Core/Computation/SpecularComputation.cpp b/Core/Computation/SpecularComputation.cpp
index 6549b64ac56..addb6e6de70 100644
--- a/Core/Computation/SpecularComputation.cpp
+++ b/Core/Computation/SpecularComputation.cpp
@@ -16,6 +16,8 @@
 #include "MultiLayer.h"
 #include "ProcessedSample.h"
 #include "ProgressHandler.h"
+#include "SpecularScalarStrategy.h"
+#include "SpecularMagneticStrategy.h"
 #include "SpecularSimulationElement.h"
 
 static_assert(std::is_copy_constructible<SpecularComputation>::value == false,
@@ -33,9 +35,9 @@ SpecularComputation::SpecularComputation(const MultiLayer& multilayer,
 {
     if (mP_processed_sample->containsMagneticMaterial()
         || mP_processed_sample->externalField() != kvector_t{})
-        m_computation_term.reset(new SpecularMatrixTerm);
+        m_computation_term.reset(new SpecularMatrixTerm(std::make_unique<SpecularMagneticStrategy>()));
     else
-        m_computation_term.reset(new SpecularScalarTerm);
+        m_computation_term.reset(new SpecularScalarTerm(std::make_unique<SpecularScalarStrategy>()));
 }
 
 SpecularComputation::~SpecularComputation() = default;
diff --git a/Core/Computation/SpecularComputationTerm.cpp b/Core/Computation/SpecularComputationTerm.cpp
index 85f5d1d0a29..1dbf8af825c 100644
--- a/Core/Computation/SpecularComputationTerm.cpp
+++ b/Core/Computation/SpecularComputationTerm.cpp
@@ -18,7 +18,9 @@
 #include "SpecularScalarStrategy.h"
 #include "SpecularSimulationElement.h"
 
-SpecularComputationTerm::SpecularComputationTerm() = default;
+SpecularComputationTerm::SpecularComputationTerm(std::unique_ptr<ISpecularStrategy> strategy) : m_Strategy(std::move(strategy)) {};
+
+SpecularScalarTerm::SpecularScalarTerm(std::unique_ptr<ISpecularStrategy> strategy) : SpecularComputationTerm(std::move(strategy)) {}
 
 SpecularComputationTerm::~SpecularComputationTerm() = default;
 
@@ -48,17 +50,19 @@ void SpecularScalarTerm::eval(SpecularSimulationElement& elem,
     elem.setIntensity(std::norm(coeff.front()->getScalarR()));
 }
 
+SpecularMatrixTerm::SpecularMatrixTerm(std::unique_ptr<ISpecularStrategy> strategy) : SpecularComputationTerm(std::move(strategy)) {}
+
 SpecularMatrixTerm::~SpecularMatrixTerm() = default;
 
 void SpecularMatrixTerm::eval(SpecularSimulationElement& elem,
                               const std::vector<Slice>& slices) const
 {
-    auto coeff = std::make_unique<SpecularMagneticStrategy>()->Execute(slices, elem.produceKz(slices));
+    auto coeff = m_Strategy->Execute(slices, elem.produceKz(slices));
     elem.setIntensity(intensity(elem, coeff.front()));
 }
 
 double SpecularMatrixTerm::intensity(const SpecularSimulationElement& elem,
-                                     SpecularMagneticStrategy::single_coeff_t& coeff) const
+                                     ISpecularStrategy::single_coeff_t& coeff) const
 {
     const auto& polarization = elem.polarizationHandler().getPolarization();
     const auto& analyzer = elem.polarizationHandler().getAnalyzerOperator();
diff --git a/Core/Computation/SpecularComputationTerm.h b/Core/Computation/SpecularComputationTerm.h
index 53390656a37..7111a1f1446 100644
--- a/Core/Computation/SpecularComputationTerm.h
+++ b/Core/Computation/SpecularComputationTerm.h
@@ -15,7 +15,7 @@
 #ifndef SPECULARCOMPUTATIONTERM_H_
 #define SPECULARCOMPUTATIONTERM_H_
 
-#include "SpecularMagneticStrategy.h"
+#include "ISpecularStrategy.h"
 
 #include <memory>
 #include <vector>
@@ -33,7 +33,7 @@ class Slice;
 class SpecularComputationTerm
 {
 public:
-    SpecularComputationTerm();
+    SpecularComputationTerm(std::unique_ptr<ISpecularStrategy> strategy);
     virtual ~SpecularComputationTerm();
 
     void setProgressHandler(ProgressHandler* p_progress);
@@ -42,12 +42,16 @@ public:
 protected:
     virtual void eval(SpecularSimulationElement& elem, const std::vector<Slice>& slices) const = 0;
 
+    std::unique_ptr<ISpecularStrategy> m_Strategy;
 private:
     std::unique_ptr<DelayedProgressCounter> mP_progress_counter;
 };
 
 class SpecularScalarTerm : public SpecularComputationTerm
 {
+public:
+    SpecularScalarTerm(std::unique_ptr<ISpecularStrategy> strategy);
+private:
     ~SpecularScalarTerm() override;
 protected:
     void eval(SpecularSimulationElement& elem, const std::vector<Slice>& slices) const override;
@@ -55,11 +59,14 @@ protected:
 
 class SpecularMatrixTerm : public SpecularComputationTerm
 {
+public:
+    SpecularMatrixTerm(std::unique_ptr<ISpecularStrategy> strategy);
+private:
     ~SpecularMatrixTerm() override;
 protected:
     void eval(SpecularSimulationElement& elem, const std::vector<Slice>& slices) const override;
     double intensity(const SpecularSimulationElement& elem,
-                     SpecularMagneticStrategy::single_coeff_t& coeff) const;
+                     ISpecularStrategy::single_coeff_t& coeff) const;
 };
 
 #endif /* SPECULARCOMPUTATIONTERM_H_ */
diff --git a/Core/Multilayer/IFresnelMap.cpp b/Core/Multilayer/IFresnelMap.cpp
index 28fc199d36e..318bfd65ea0 100644
--- a/Core/Multilayer/IFresnelMap.cpp
+++ b/Core/Multilayer/IFresnelMap.cpp
@@ -15,7 +15,8 @@
 #include "IFresnelMap.h"
 #include "Slice.h"
 
-IFresnelMap::IFresnelMap() : m_use_cache(true) {}
+IFresnelMap::IFresnelMap(std::unique_ptr<ISpecularStrategy> strategy) : m_use_cache(true),
+                                                                        m_Strategy(std::move(strategy)) {}
 
 void IFresnelMap::setSlices(const std::vector<Slice>& slices)
 {
diff --git a/Core/Multilayer/IFresnelMap.h b/Core/Multilayer/IFresnelMap.h
index 4b2b3c3472e..2dc6547abd9 100644
--- a/Core/Multilayer/IFresnelMap.h
+++ b/Core/Multilayer/IFresnelMap.h
@@ -16,6 +16,7 @@
 #define IFRESNELMAP_H
 
 #include "ILayerRTCoefficients.h"
+#include "ISpecularStrategy.h"
 #include "Slice.h"
 #include "Vectors3D.h"
 #include "WinDllMacros.h"
@@ -32,7 +33,7 @@ class SimulationElement;
 class BA_CORE_API_ IFresnelMap
 {
 public:
-    IFresnelMap();
+    IFresnelMap(std::unique_ptr<ISpecularStrategy> strategy);
     virtual ~IFresnelMap();
 
     //! Retrieves the amplitude coefficients for a (time-reversed) outgoing wavevector.
@@ -59,6 +60,8 @@ protected:
 
     std::vector<Slice> m_slices;
     bool m_use_cache;
+
+    std::unique_ptr<ISpecularStrategy> m_Strategy;
 };
 
 #endif // IFRESNELMAP_H
diff --git a/Core/Multilayer/MatrixFresnelMap.cpp b/Core/Multilayer/MatrixFresnelMap.cpp
index e25247094e2..03bfbfb578b 100644
--- a/Core/Multilayer/MatrixFresnelMap.cpp
+++ b/Core/Multilayer/MatrixFresnelMap.cpp
@@ -20,7 +20,7 @@
 #include <functional>
 
 
-MatrixFresnelMap::MatrixFresnelMap() = default;
+MatrixFresnelMap::MatrixFresnelMap(std::unique_ptr<ISpecularStrategy> strategy) : IFresnelMap(std::move(strategy)) {};
 
 MatrixFresnelMap::~MatrixFresnelMap() = default;
 
@@ -60,7 +60,7 @@ MatrixFresnelMap::getCoefficients(const kvector_t& kvec, size_t layer_index,
                                   const std::vector<Slice>& slices, CoefficientHash& hash_table) const
 {
     if (!m_use_cache) {
-        auto coeffs = std::make_unique<SpecularMagneticStrategy>()->Execute(slices, kvec);
+        auto coeffs = m_Strategy->Execute(slices, kvec);
         return ISpecularStrategy::single_coeff_t(coeffs[layer_index]->clone());
     }
     const auto& coef_vector = getCoefficientsFromCache(kvec, slices, hash_table);
@@ -73,6 +73,6 @@ MatrixFresnelMap::getCoefficientsFromCache(kvector_t kvec, const std::vector<Sli
 {
     auto it = hash_table.find(kvec);
     if (it == hash_table.end())
-        it = hash_table.emplace(kvec, std::make_unique<SpecularMagneticStrategy>()->Execute(slices, kvec)).first;
+        it = hash_table.emplace(kvec, m_Strategy->Execute(slices, kvec)).first;
     return it->second;
 }
diff --git a/Core/Multilayer/MatrixFresnelMap.h b/Core/Multilayer/MatrixFresnelMap.h
index 7c8fecf2f78..06b3a23afb6 100644
--- a/Core/Multilayer/MatrixFresnelMap.h
+++ b/Core/Multilayer/MatrixFresnelMap.h
@@ -35,7 +35,7 @@ class SimulationElement;
 class BA_CORE_API_ MatrixFresnelMap : public IFresnelMap
 {
 public:
-    MatrixFresnelMap();
+    MatrixFresnelMap(std::unique_ptr<ISpecularStrategy> strategy);
     ~MatrixFresnelMap() override;
 
     MatrixFresnelMap(const MatrixFresnelMap& other) = delete;
diff --git a/Core/Multilayer/ScalarFresnelMap.cpp b/Core/Multilayer/ScalarFresnelMap.cpp
index 56e95614069..1b24d8f3ecb 100644
--- a/Core/Multilayer/ScalarFresnelMap.cpp
+++ b/Core/Multilayer/ScalarFresnelMap.cpp
@@ -19,7 +19,7 @@
 #include "Vectors3D.h"
 #include <functional>
 
-ScalarFresnelMap::ScalarFresnelMap() {}
+ScalarFresnelMap::ScalarFresnelMap(std::unique_ptr<ISpecularStrategy> strategy) : IFresnelMap(std::move(strategy)) {}
 
 ScalarFresnelMap::~ScalarFresnelMap() = default;
 
@@ -39,21 +39,20 @@ std::unique_ptr<const ILayerRTCoefficients>
 ScalarFresnelMap::getCoefficients(const kvector_t& kvec, size_t layer_index) const
 {
     if (!m_use_cache) {
-        auto coeffs = std::make_unique<SpecularScalarStrategy>()->Execute(m_slices, kvec);
-        return SpecularScalarStrategy::single_coeff_t(coeffs[layer_index]->clone());
+        auto coeffs = m_Strategy->Execute(m_slices, kvec);
+        return ISpecularStrategy::single_coeff_t(coeffs[layer_index]->clone());
     }
     const auto& coef_vector = getCoefficientsFromCache(kvec);
-    return SpecularScalarStrategy::single_coeff_t(coef_vector[layer_index]->clone());
+    return ISpecularStrategy::single_coeff_t(coef_vector[layer_index]->clone());
 }
 
-const SpecularScalarStrategy::coeffs_t&
+const ISpecularStrategy::coeffs_t&
 ScalarFresnelMap::getCoefficientsFromCache(kvector_t kvec) const
 {
     std::pair<double, double> k2_theta(kvec.mag2(), kvec.theta());
     auto it = m_cache.find(k2_theta);
     if (it == m_cache.end()) {
-        it = m_cache.emplace(k2_theta,
-                             std::make_unique<SpecularScalarStrategy>()->Execute(m_slices, kvec)).first;
+        it = m_cache.emplace(k2_theta, m_Strategy->Execute(m_slices, kvec)).first;
     }
     return it->second;
 }
diff --git a/Core/Multilayer/ScalarFresnelMap.h b/Core/Multilayer/ScalarFresnelMap.h
index 9a5ef0ce575..68d19d5b117 100644
--- a/Core/Multilayer/ScalarFresnelMap.h
+++ b/Core/Multilayer/ScalarFresnelMap.h
@@ -17,7 +17,7 @@
 
 #include "IFresnelMap.h"
 #include "ScalarRTCoefficients.h"
-#include "SpecularScalarStrategy.h"
+#include "ISpecularStrategy.h"
 #include <cstddef>
 #include <unordered_map>
 #include <utility>
@@ -33,7 +33,7 @@ class Slice;
 class BA_CORE_API_ ScalarFresnelMap : public IFresnelMap
 {
 public:
-    ScalarFresnelMap();
+    ScalarFresnelMap(std::unique_ptr<ISpecularStrategy> strategy);
     ~ScalarFresnelMap() final;
 
     ScalarFresnelMap(const ScalarFresnelMap& other) = delete;
@@ -52,8 +52,8 @@ private:
 
     std::unique_ptr<const ILayerRTCoefficients> getCoefficients(const kvector_t& kvec,
                                                                 size_t layer_index) const override;
-    const SpecularScalarStrategy::coeffs_t& getCoefficientsFromCache(kvector_t kvec) const;
-    mutable std::unordered_map<std::pair<double, double>, SpecularScalarStrategy::coeffs_t,
+    const ISpecularStrategy::coeffs_t& getCoefficientsFromCache(kvector_t kvec) const;
+    mutable std::unordered_map<std::pair<double, double>, ISpecularStrategy::coeffs_t,
                                Hash2Doubles> m_cache;
 };
 
-- 
GitLab