From 9e26c3eca65456403dcf36b47ef791983edff84e Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Fri, 1 Apr 2016 17:17:50 +0200
Subject: [PATCH] implemented vector products for mixed arguments
 (complex/double)

---
 Core/Algorithms/RectangularDetector.cpp |  4 +--
 Core/Geometry/BasicVector3D.cpp         | 37 ++++++++++++++++++++-----
 Core/Geometry/BasicVector3D.h           | 26 +++++++++--------
 3 files changed, 47 insertions(+), 20 deletions(-)

diff --git a/Core/Algorithms/RectangularDetector.cpp b/Core/Algorithms/RectangularDetector.cpp
index 5b4b49a2765..bc7ee15db84 100644
--- a/Core/Algorithms/RectangularDetector.cpp
+++ b/Core/Algorithms/RectangularDetector.cpp
@@ -125,8 +125,8 @@ IPixelMap *RectangularDetector::createPixelMap(size_t index) const
 
     Bin1D u_bin = u_axis.getBin(u_index);
     Bin1D v_bin = v_axis.getBin(v_index);
-    kvector_t corner_position = m_normal_to_detector
-            + (u_bin.m_lower - m_u0)*m_u_unit + (v_bin.m_lower - m_v0)*m_v_unit;
+    kvector_t corner_position( m_normal_to_detector
+            + (u_bin.m_lower - m_u0)*m_u_unit + (v_bin.m_lower - m_v0)*m_v_unit );
     kvector_t width = u_bin.getBinSize()*m_u_unit;
     kvector_t height = v_bin.getBinSize()*m_v_unit;
     return new RectPixelMap(corner_position, width, height);
diff --git a/Core/Geometry/BasicVector3D.cpp b/Core/Geometry/BasicVector3D.cpp
index 936cb547e49..9c17e9ac14a 100644
--- a/Core/Geometry/BasicVector3D.cpp
+++ b/Core/Geometry/BasicVector3D.cpp
@@ -79,29 +79,52 @@ BasicVector3D<std::complex<double>> BasicVector3D<double>::complex() const
 // Combine two vectors
 // -----------------------------------------------------------------------------
 
-//! Returns dot product of vectors (antilinear in the first [=self] argument).
-template<>
+//! Returns dot product of complex vectors (antilinear in the first [=self] argument).
+template<> template<>
 complex_t BasicVector3D<complex_t>::dot(const BasicVector3D<complex_t>& v) const
 {
      return std::conj(x())*v.x()+std::conj(y())*v.y()+std::conj(z())*v.z();
 }
 
-template<>
+//! Returns mixed dot product of complex and double vectors (antilinear in the complex argument).
+template<> template<>
+complex_t BasicVector3D<complex_t>::dot(const BasicVector3D<double>& v) const
+{
+     return std::conj( x()*v.x()+y()*v.y()+z()*v.z() );
+}
+
+//! Returns mixed dot product of double and complex vectors (linear in the complex argument).
+template<> template<>
+complex_t BasicVector3D<double>::dot(const BasicVector3D<complex_t>& v) const
+{
+     return x()*v.x()+y()*v.y()+z()*v.z();
+}
+
+//! Returns dot product of double-typed vectors.
+template<> template<>
 double BasicVector3D<double>::dot(const BasicVector3D<double>& v) const
 {
    return x()*v.x()+y()*v.y()+z()*v.z();
 }
 
- //! Returns cross product of vectors.
-template<>
-BasicVector3D<double> BasicVector3D<double>::cross(
-    const BasicVector3D<double>& v) const
+ //! Returns cross product of double-typed vectors.
+template<> template<>
+BasicVector3D<double> BasicVector3D<double>::cross(const BasicVector3D<double>& v) const
 {
     return BasicVector3D<double>(y()*v.z()-v.y()*z(),
                                  z()*v.x()-v.z()*x(),
                                  x()*v.y()-v.x()*y());
 }
 
+ //! Returns mixed cross product of double and complex vectors.
+template<> template<>
+BasicVector3D<complex_t> BasicVector3D<double>::cross(const BasicVector3D<complex_t>& v) const
+{
+    return BasicVector3D<complex_t>(y()*v.z()-v.y()*z(),
+                                    z()*v.x()-v.z()*x(),
+                                    x()*v.y()-v.x()*y());
+}
+
 //! Returns angle with respect to another vector.
 template<>
 double BasicVector3D<double>::angle(const BasicVector3D<double>& v) const
diff --git a/Core/Geometry/BasicVector3D.h b/Core/Geometry/BasicVector3D.h
index af4933f7ffe..b63d665e80f 100644
--- a/Core/Geometry/BasicVector3D.h
+++ b/Core/Geometry/BasicVector3D.h
@@ -90,11 +90,13 @@ public:
     { v_[0] -= v.v_[0]; v_[1] -= v.v_[1]; v_[2] -= v.v_[2]; return *this; }
 
     //! Multiplies this with a scalar, and returns result.
-    inline BasicVector3D<T>& operator*=(double a)
+    template<class U>
+    inline auto operator*=(U a) -> BasicVector3D<decltype(this->x()*a)>&
     { v_[0] *= a; v_[1] *= a; v_[2] *= a; return *this; }
 
     //! Divides this by a scalar, and returns result.
-    inline BasicVector3D<T>& operator/=(double a)
+    template<class U>
+    inline auto operator/=(U a) -> BasicVector3D<decltype(this->x()*a)>&
     { v_[0] /= a; v_[1] /= a; v_[2] /= a; return *this; }
 
     // -------------------------------------------------------------------------
@@ -144,10 +146,12 @@ public:
     // -------------------------------------------------------------------------
 
     //! Returns dot product of vectors (antilinear in the first [=self] argument).
-    T dot(const BasicVector3D<T>& v) const;
+    template<class U>
+    auto dot(const BasicVector3D<U>& v) const -> decltype(this->x()*v.x());
 
     //! Returns cross product of vectors.
-    BasicVector3D<T> cross(const BasicVector3D<T>& v ) const;
+    template<class U>
+    auto cross(const BasicVector3D<U>& v) const -> BasicVector3D<decltype(this->x()*v.x())>;
 
     //! Returns angle with respect to another vector.
     double angle(const BasicVector3D<T>& v) const;
@@ -217,14 +221,14 @@ inline BasicVector3D<T> operator-(const BasicVector3D<T>& a, const BasicVector3D
 //! Multiplication vector by scalar.
 //! @relates BasicVector3D
 template <class T, class U>
-inline BasicVector3D<T> operator* (const BasicVector3D<T>& v, U a)
-{ return BasicVector3D<T>(v.x()*a, v.y()*a, v.z()*a); }
+inline auto operator* (const BasicVector3D<T>& v, const U a) -> BasicVector3D<decltype(v.x()*a)>
+{ return BasicVector3D<decltype(v.x()*a)>(v.x()*a, v.y()*a, v.z()*a); }
 
 //! Multiplication scalar by vector.
 //! @relates BasicVector3D
 template <class T, class U>
-inline BasicVector3D<T> operator* (U a, const BasicVector3D<T>& v)
-{ return BasicVector3D<T>(a*v.x(), a*v.y(), a*v.z()); }
+inline auto operator* (const U a, const BasicVector3D<T>& v) -> BasicVector3D<decltype(a*v.x())>
+{ return BasicVector3D<decltype(a*v.x())>(a*v.x(), a*v.y(), a*v.z()); }
 
 // vector*vector not supported
 //    (We do not provide the operator form a*b of the dot product:
@@ -262,13 +266,13 @@ BA_CORE_API_ BasicVector3D<double> vecOfLambdaAlphaPhi(const double _lambda, con
 // ?? for API generation ??
 // =============================================================================
 
-template<> BA_CORE_API_ std::complex<double> BasicVector3D<std::complex<double> >::dot(
+template<> template<> BA_CORE_API_ std::complex<double> BasicVector3D<std::complex<double> >::dot(
         const BasicVector3D<std::complex<double> >& v) const;
 
-template<> BA_CORE_API_ double BasicVector3D<double>::dot(
+template<> template<> BA_CORE_API_ double BasicVector3D<double>::dot(
         const BasicVector3D<double>& v) const;
 
-template<> BA_CORE_API_ BasicVector3D<double> BasicVector3D<double>::cross(
+template<> template<> BA_CORE_API_ BasicVector3D<double> BasicVector3D<double>::cross(
         const BasicVector3D<double>& v) const;
 
 template<> BA_CORE_API_ double BasicVector3D<double>::phi() const;
-- 
GitLab