From 25802854a9b622a79bb5b7edea770b0e80f46984 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Sat, 27 Nov 2021 09:32:39 +0100
Subject: [PATCH] merge BasicVector3D into Vectors3D

---
 Base/Vector/BasicVector3D.h             | 381 ------------------------
 Base/Vector/Vectors3D.h                 | 364 +++++++++++++++++++++-
 Wrap/Swig/fromBase.i                    |   3 +-
 Wrap/Swig/libBornAgainBase.i            |   1 -
 Wrap/Swig/libBornAgainResample.i        |   2 +-
 auto/Wrap/doxygenBase.i                 | 143 ++++++++-
 auto/Wrap/libBornAgainBase.py           |   6 +-
 auto/Wrap/libBornAgainBase_wrap.cpp     |  20 +-
 auto/Wrap/libBornAgainCore_wrap.cpp     |  14 +-
 auto/Wrap/libBornAgainDevice_wrap.cpp   |  14 +-
 auto/Wrap/libBornAgainResample_wrap.cpp |  16 +-
 auto/Wrap/libBornAgainSample_wrap.cpp   |  14 +-
 12 files changed, 546 insertions(+), 432 deletions(-)
 delete mode 100644 Base/Vector/BasicVector3D.h

diff --git a/Base/Vector/BasicVector3D.h b/Base/Vector/BasicVector3D.h
deleted file mode 100644
index ed1f738f51a..00000000000
--- a/Base/Vector/BasicVector3D.h
+++ /dev/null
@@ -1,381 +0,0 @@
-//  ************************************************************************************************
-//
-//  BornAgain: simulate and fit reflection and scattering
-//
-//! @file      Base/Vector/BasicVector3D.h
-//! @brief     Declares and partly implements template class BasicVector3D.
-//!
-//! @homepage  http://www.bornagainproject.org
-//! @license   GNU General Public License v3 or higher (see COPYING)
-//! @copyright Forschungszentrum Jülich GmbH 2018
-//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
-//!
-//! Forked from CLHEP/Geometry by E. Chernyaev <Evgueni.Tcherniaev@cern.ch>,
-//! then reworked beyond recognition. Removed split of point and vector semantics.
-//! Transforms are relegated to a separate class Transform3D.
-//
-//  ************************************************************************************************
-
-#ifndef BORNAGAIN_BASE_VECTOR_BASICVECTOR3D_H
-#define BORNAGAIN_BASE_VECTOR_BASICVECTOR3D_H
-
-#include "Base/Types/Complex.h"
-#include <array>
-
-//! Three-dimensional vector template, for use with integer, double, or complex components.
-
-template <class T> class BasicVector3D : public std::array<T,3> {
-private:
-    using super = std::array<T,3>;
-
-public:
-    // -------------------------------------------------------------------------
-    // Constructors and other set functions
-    // -------------------------------------------------------------------------
-
-    //! Constructs the null vector.
-    BasicVector3D() : super{0., 0., 0.} {}
-
-    //! Constructs a vector from cartesian components.
-    BasicVector3D(const T x, const T y, const T z) : super{x,y,z} {}
-
-    // -------------------------------------------------------------------------
-    // Component access
-    // -------------------------------------------------------------------------
-
-    //! Returns x-component in cartesian coordinate system.
-    inline T x() const { return (*this)[0]; }
-    //! Returns y-component in cartesian coordinate system.
-    inline T y() const { return (*this)[1]; }
-    //! Returns z-component in cartesian coordinate system.
-    inline T z() const { return (*this)[2]; }
-
-    //! Sets x-component in cartesian coordinate system.
-    void setX(const T& a) { (*this)[0] = a; }
-    //! Sets y-component in cartesian coordinate system.
-    void setY(const T& a) { (*this)[1] = a; }
-    //! Sets z-component in cartesian coordinate system.
-    void setZ(const T& a) { (*this)[2] = a; }
-
-    // -------------------------------------------------------------------------
-    // In-place operations
-    // -------------------------------------------------------------------------
-
-    //! Adds other vector to this, and returns result.
-    BasicVector3D<T>& operator+=(const BasicVector3D<T>& v)
-    {
-        (*this)[0] += v[0];
-        (*this)[1] += v[1];
-        (*this)[2] += v[2];
-        return *this;
-    }
-
-    //! Subtracts other vector from this, and returns result.
-    BasicVector3D<T>& operator-=(const BasicVector3D<T>& v)
-    {
-        (*this)[0] -= v[0];
-        (*this)[1] -= v[1];
-        (*this)[2] -= v[2];
-        return *this;
-    }
-
-    //! Multiplies this with a scalar, and returns result.
-#ifndef SWIG
-    template <class U> auto operator*=(U a)
-    {
-        (*this)[0] *= a;
-        (*this)[1] *= a;
-        (*this)[2] *= a;
-        return *this;
-    }
-#endif // USER_API
-
-    //! Divides this by a scalar, and returns result.
-#ifndef SWIG
-    template <class U> auto operator/=(U a)
-    {
-        (*this)[0] /= a;
-        (*this)[1] /= a;
-        (*this)[2] /= a;
-        return *this;
-    }
-#endif // USER_API
-
-    // -------------------------------------------------------------------------
-    // Functions of this (with no further argument)
-    // -------------------------------------------------------------------------
-
-    //! Returns complex conjugate vector
-    BasicVector3D<T> conj() const;
-
-    //! Returns magnitude squared of the vector.
-    double mag2() const { return std::norm(x()) + std::norm(y()) + std::norm(z()); }
-
-    //! Returns magnitude of the vector.
-    double mag() const { return sqrt(mag2()); }
-
-    //! Returns squared distance from z axis.
-    double magxy2() const { return std::norm(x()) + std::norm(y()); }
-
-    //! Returns distance from z axis.
-    double magxy() const { return sqrt(magxy2()); }
-
-    //! Returns azimuth angle.
-    double phi() const;
-
-    //! Returns polar angle.
-    double theta() const;
-
-    //! Returns cosine of polar angle.
-    double cosTheta() const;
-
-    //! Returns squared sine of polar angle.
-    double sin2Theta() const;
-
-    //! Returns unit vector in direction of this. Throws for null vector.
-    BasicVector3D<T> unit() const;
-
-    //! Returns this, trivially converted to complex type.
-    BasicVector3D<complex_t> complex() const;
-
-    //! Returns real parts.
-    BasicVector3D<double> real() const;
-
-    // -------------------------------------------------------------------------
-    // Functions of this and another vector
-    // -------------------------------------------------------------------------
-
-    //! Returns dot product of vectors (antilinear in the first [=self] argument).
-#ifndef SWIG
-    template <class U> auto dot(const BasicVector3D<U>& v) const;
-#endif // USER_API
-
-    //! Returns cross product of vectors (linear in both arguments).
-#ifndef SWIG
-    template <class U> auto cross(const BasicVector3D<U>& v) const;
-#endif // USER_API
-
-    //! Returns angle with respect to another vector.
-    double angle(const BasicVector3D<T>& v) const;
-
-    //! Returns projection of this onto other vector: (this*v)*v/|v|^2.
-    BasicVector3D<T> project(const BasicVector3D<T>& v) const
-    {
-        return dot(v) * v / v.mag2();
-    }
-
-    // -------------------------------------------------------------------------
-    // Rotations
-    // -------------------------------------------------------------------------
-
-    //! Returns result of rotation around x-axis.
-    BasicVector3D<T> rotatedX(double a) const;
-    //! Returns result of rotation around y-axis.
-    BasicVector3D<T> rotatedY(double a) const;
-    //! Returns result of rotation around z-axis.
-    BasicVector3D<T> rotatedZ(double a) const
-    {
-        return BasicVector3D<T>(cos(a) * x() + sin(a) * y(), -sin(a) * x() + cos(a) * y(), z());
-    }
-    //! Returns result of rotation around the axis specified by another vector.
-    BasicVector3D<T> rotated(double a, const BasicVector3D<T>& v) const;
-};
-
-// =============================================================================
-// Non-member functions
-// =============================================================================
-
-//! Output to stream.
-//! @relates BasicVector3D
-template <class T> std::ostream& operator<<(std::ostream& os, const BasicVector3D<T>& a)
-{
-    return os << "(" << a.x() << "," << a.y() << "," << a.z() << ")";
-}
-
-// -----------------------------------------------------------------------------
-// Unary operators
-// -----------------------------------------------------------------------------
-
-//! Unary plus.
-//! @relates BasicVector3D
-template <class T> inline BasicVector3D<T> operator+(const BasicVector3D<T>& v)
-{
-    return v;
-}
-
-//! Unary minus.
-//! @relates BasicVector3D
-template <class T> inline BasicVector3D<T> operator-(const BasicVector3D<T>& v)
-{
-    return {-v.x(), -v.y(), -v.z()};
-}
-
-// -----------------------------------------------------------------------------
-// Binary operators
-// -----------------------------------------------------------------------------
-
-//! Addition of two vectors.
-//! @relates BasicVector3D
-template <class T>
-inline BasicVector3D<T> operator+(const BasicVector3D<T>& a, const BasicVector3D<T>& b)
-{
-    return {a.x() + b.x(), a.y() + b.y(), a.z() + b.z()};
-}
-
-//! Subtraction of two vectors.
-//! @relates BasicVector3D
-template <class T>
-inline BasicVector3D<T> operator-(const BasicVector3D<T>& a, const BasicVector3D<T>& b)
-{
-    return {a.x() - b.x(), a.y() - b.y(), a.z() - b.z()};
-}
-
-//! Multiplication vector by scalar.
-//! @relates BasicVector3D
-#ifndef SWIG
-template <class T, class U> inline auto operator*(const BasicVector3D<T>& v, const U a)
-{
-    return BasicVector3D<decltype(v.x() * v.x())>(v.x() * a, v.y() * a, v.z() * a);
-}
-#endif // USER_API
-
-//! Multiplication scalar by vector.
-//! @relates BasicVector3D
-#ifndef SWIG
-template <class T, class U> inline auto operator*(const U a, const BasicVector3D<T>& v)
-{
-    return BasicVector3D<decltype(a * v.x())>(a * v.x(), a * v.y(), a * v.z());
-}
-#endif // USER_API
-
-// vector*vector not supported
-//    (We do not provide the operator form a*b of the dot product:
-//     Though nice to write, and in some cases perfectly justified,
-//     in general it tends to make expressions more difficult to read.)
-
-//! Division 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);
-}
-
-// =============================================================================
-// ?? for API generation ??
-// =============================================================================
-
-//! Returns dot product of (complex) vectors (antilinear in the first [=self] argument).
-#ifndef SWIG
-template <class T>
-template <class U>
-inline auto BasicVector3D<T>::dot(const BasicVector3D<U>& v) const
-{
-    BasicVector3D<T> left_star = this->conj();
-    return left_star.x() * v.x() + left_star.y() * v.y() + left_star.z() * v.z();
-}
-#endif // USER_API
-
-//! Returns cross product of (complex) vectors.
-#ifndef SWIG
-template <class T>
-template <class U>
-inline auto BasicVector3D<T>::cross(const BasicVector3D<U>& v) const
-{
-    return BasicVector3D<decltype(this->x() * v.x())>(
-        y() * v.z() - v.y() * z(), z() * v.x() - v.z() * x(), x() * v.y() - v.x() * y());
-}
-#endif // USER_API
-
-// -----------------------------------------------------------------------------
-// Functions of this (with no further argument)
-// -----------------------------------------------------------------------------
-
-//! Returns complex conjugate vector
-template <> inline BasicVector3D<double> BasicVector3D<double>::conj() const
-{
-    return *this;
-}
-
-template <> inline BasicVector3D<complex_t> BasicVector3D<complex_t>::conj() const
-{
-    return {std::conj(x()), std::conj(y()), std::conj(z())};
-}
-
-//! Returns azimuth angle.
-template <> inline double BasicVector3D<double>::phi() const
-{
-    return x() == 0.0 && y() == 0.0 ? 0.0 : std::atan2(-y(), x());
-}
-
-//! Returns polar angle.
-template <> inline double BasicVector3D<double>::theta() const
-{
-    return x() == 0.0 && y() == 0.0 && z() == 0.0 ? 0.0 : std::atan2(magxy(), z());
-}
-
-//! Returns cosine of polar angle.
-template <> inline double BasicVector3D<double>::cosTheta() const
-{
-    return mag() == 0 ? 1 : z() / mag();
-}
-
-//! Returns squared sine of polar angle.
-template <> inline double BasicVector3D<double>::sin2Theta() const
-{
-    return mag2() == 0 ? 0 : magxy2() / mag2();
-}
-
-//! Returns this, trivially converted to complex type.
-template <> inline BasicVector3D<complex_t> BasicVector3D<double>::complex() const
-{
-    return {x(), y(), z()};
-}
-
-//! Returns real parts.
-template <> inline BasicVector3D<double> BasicVector3D<double>::real() const
-{
-    return *this;
-}
-
-template <> inline BasicVector3D<double> BasicVector3D<complex_t>::real() const
-{
-    return {x().real(), y().real(), z().real()};
-}
-
-//! Returns unit vector in direction of this. Throws for null vector.
-template <> inline BasicVector3D<double> BasicVector3D<double>::unit() const
-{
-    double len = mag();
-    if (len == 0.0)
-        throw std::runtime_error("Cannot normalize zero vector");
-    return {x() / len, y() / len, z() / len};
-}
-
-template <> inline BasicVector3D<complex_t> BasicVector3D<complex_t>::unit() const
-{
-    double len = mag();
-    if (len == 0.0)
-        throw std::runtime_error("Cannot normalize zero vector");
-    return {x() / len, y() / len, z() / len};
-}
-
-// -----------------------------------------------------------------------------
-// Combine two vectors
-// -----------------------------------------------------------------------------
-
-//! Returns angle with respect to another vector.
-template <> inline double BasicVector3D<double>::angle(const BasicVector3D<double>& v) const
-{
-    double cosa = 0;
-    double ptot = mag() * v.mag();
-    if (ptot > 0) {
-        cosa = dot(v) / ptot;
-        if (cosa > 1)
-            cosa = 1;
-        if (cosa < -1)
-            cosa = -1;
-    }
-    return std::acos(cosa);
-}
-
-#endif // BORNAGAIN_BASE_VECTOR_BASICVECTOR3D_H
diff --git a/Base/Vector/Vectors3D.h b/Base/Vector/Vectors3D.h
index aa5d47d5337..b3ce2a25cce 100644
--- a/Base/Vector/Vectors3D.h
+++ b/Base/Vector/Vectors3D.h
@@ -3,7 +3,7 @@
 //  BornAgain: simulate and fit reflection and scattering
 //
 //! @file      Base/Vector/Vectors3D.h
-//! @brief     Defines basic vectors in Z^3, R^3, C^3.
+//! @brief     Defines and implements three-dimensional vector types I3, R3, C3
 //!
 //! @homepage  http://www.bornagainproject.org
 //! @license   GNU General Public License v3 or higher (see COPYING)
@@ -15,10 +15,370 @@
 #ifndef BORNAGAIN_BASE_VECTOR_VECTORS3D_H
 #define BORNAGAIN_BASE_VECTOR_VECTORS3D_H
 
-#include "Base/Vector/BasicVector3D.h"
+#include "Base/Types/Complex.h"
+#include <array>
+
+template <class T> class BasicVector3D;
 
 using I3 = BasicVector3D<int>;
 using R3 = BasicVector3D<double>;
 using C3 = BasicVector3D<complex_t>;
 
+
+//! Three-dimensional vector template, for use with integer, double, or complex components.
+
+template <class T> class BasicVector3D : public std::array<T,3> {
+private:
+    using super = std::array<T,3>;
+
+public:
+    // -------------------------------------------------------------------------
+    // Constructors and other set functions
+    // -------------------------------------------------------------------------
+
+    //! Constructs the null vector.
+    BasicVector3D() : super{0., 0., 0.} {}
+
+    //! Constructs a vector from cartesian components.
+    BasicVector3D(const T x, const T y, const T z) : super{x,y,z} {}
+
+    // -------------------------------------------------------------------------
+    // Component access
+    // -------------------------------------------------------------------------
+
+    //! Returns x-component in cartesian coordinate system.
+    inline T x() const { return (*this)[0]; }
+    //! Returns y-component in cartesian coordinate system.
+    inline T y() const { return (*this)[1]; }
+    //! Returns z-component in cartesian coordinate system.
+    inline T z() const { return (*this)[2]; }
+
+    //! Sets x-component in cartesian coordinate system.
+    void setX(const T& a) { (*this)[0] = a; }
+    //! Sets y-component in cartesian coordinate system.
+    void setY(const T& a) { (*this)[1] = a; }
+    //! Sets z-component in cartesian coordinate system.
+    void setZ(const T& a) { (*this)[2] = a; }
+
+    // -------------------------------------------------------------------------
+    // In-place operations
+    // -------------------------------------------------------------------------
+
+    //! Adds other vector to this, and returns result.
+    BasicVector3D<T>& operator+=(const BasicVector3D<T>& v)
+    {
+        (*this)[0] += v[0];
+        (*this)[1] += v[1];
+        (*this)[2] += v[2];
+        return *this;
+    }
+
+    //! Subtracts other vector from this, and returns result.
+    BasicVector3D<T>& operator-=(const BasicVector3D<T>& v)
+    {
+        (*this)[0] -= v[0];
+        (*this)[1] -= v[1];
+        (*this)[2] -= v[2];
+        return *this;
+    }
+
+    //! Multiplies this with a scalar, and returns result.
+#ifndef SWIG
+    template <class U> auto operator*=(U a)
+    {
+        (*this)[0] *= a;
+        (*this)[1] *= a;
+        (*this)[2] *= a;
+        return *this;
+    }
+#endif // USER_API
+
+    //! Divides this by a scalar, and returns result.
+#ifndef SWIG
+    template <class U> auto operator/=(U a)
+    {
+        (*this)[0] /= a;
+        (*this)[1] /= a;
+        (*this)[2] /= a;
+        return *this;
+    }
+#endif // USER_API
+
+    // -------------------------------------------------------------------------
+    // Functions of this (with no further argument)
+    // -------------------------------------------------------------------------
+
+    //! Returns complex conjugate vector
+    BasicVector3D<T> conj() const;
+
+    //! Returns magnitude squared of the vector.
+    double mag2() const { return std::norm(x()) + std::norm(y()) + std::norm(z()); }
+
+    //! Returns magnitude of the vector.
+    double mag() const { return sqrt(mag2()); }
+
+    //! Returns squared distance from z axis.
+    double magxy2() const { return std::norm(x()) + std::norm(y()); }
+
+    //! Returns distance from z axis.
+    double magxy() const { return sqrt(magxy2()); }
+
+    //! Returns azimuth angle.
+    double phi() const;
+
+    //! Returns polar angle.
+    double theta() const;
+
+    //! Returns cosine of polar angle.
+    double cosTheta() const;
+
+    //! Returns squared sine of polar angle.
+    double sin2Theta() const;
+
+    //! Returns unit vector in direction of this. Throws for null vector.
+    BasicVector3D<T> unit() const;
+
+    //! Returns this, trivially converted to complex type.
+    C3 complex() const;
+
+    //! Returns real parts.
+    R3 real() const;
+
+    // -------------------------------------------------------------------------
+    // Functions of this and another vector
+    // -------------------------------------------------------------------------
+
+    //! Returns dot product of vectors (antilinear in the first [=self] argument).
+#ifndef SWIG
+    template <class U> auto dot(const BasicVector3D<U>& v) const;
+#endif // USER_API
+
+    //! Returns cross product of vectors (linear in both arguments).
+#ifndef SWIG
+    template <class U> auto cross(const BasicVector3D<U>& v) const;
+#endif // USER_API
+
+    //! Returns angle with respect to another vector.
+    double angle(const BasicVector3D<T>& v) const;
+
+    //! Returns projection of this onto other vector: (this*v)*v/|v|^2.
+    BasicVector3D<T> project(const BasicVector3D<T>& v) const
+    {
+        return dot(v) * v / v.mag2();
+    }
+
+    // -------------------------------------------------------------------------
+    // Rotations
+    // -------------------------------------------------------------------------
+
+    //! Returns result of rotation around x-axis.
+    BasicVector3D<T> rotatedX(double a) const;
+    //! Returns result of rotation around y-axis.
+    BasicVector3D<T> rotatedY(double a) const;
+    //! Returns result of rotation around z-axis.
+    BasicVector3D<T> rotatedZ(double a) const
+    {
+        return BasicVector3D<T>(cos(a) * x() + sin(a) * y(), -sin(a) * x() + cos(a) * y(), z());
+    }
+    //! Returns result of rotation around the axis specified by another vector.
+    BasicVector3D<T> rotated(double a, const BasicVector3D<T>& v) const;
+};
+
+// =============================================================================
+// Non-member functions
+// =============================================================================
+
+//! Output to stream.
+//! @relates BasicVector3D
+template <class T> std::ostream& operator<<(std::ostream& os, const BasicVector3D<T>& a)
+{
+    return os << "(" << a.x() << "," << a.y() << "," << a.z() << ")";
+}
+
+// -----------------------------------------------------------------------------
+// Unary operators
+// -----------------------------------------------------------------------------
+
+//! Unary plus.
+//! @relates BasicVector3D
+template <class T> inline BasicVector3D<T> operator+(const BasicVector3D<T>& v)
+{
+    return v;
+}
+
+//! Unary minus.
+//! @relates BasicVector3D
+template <class T> inline BasicVector3D<T> operator-(const BasicVector3D<T>& v)
+{
+    return {-v.x(), -v.y(), -v.z()};
+}
+
+// -----------------------------------------------------------------------------
+// Binary operators
+// -----------------------------------------------------------------------------
+
+//! Addition of two vectors.
+//! @relates BasicVector3D
+template <class T>
+inline BasicVector3D<T> operator+(const BasicVector3D<T>& a, const BasicVector3D<T>& b)
+{
+    return {a.x() + b.x(), a.y() + b.y(), a.z() + b.z()};
+}
+
+//! Subtraction of two vectors.
+//! @relates BasicVector3D
+template <class T>
+inline BasicVector3D<T> operator-(const BasicVector3D<T>& a, const BasicVector3D<T>& b)
+{
+    return {a.x() - b.x(), a.y() - b.y(), a.z() - b.z()};
+}
+
+//! Multiplication vector by scalar.
+//! @relates BasicVector3D
+#ifndef SWIG
+template <class T, class U> inline auto operator*(const BasicVector3D<T>& v, const U a)
+{
+    return BasicVector3D<decltype(v.x() * v.x())>(v.x() * a, v.y() * a, v.z() * a);
+}
+#endif // USER_API
+
+//! Multiplication scalar by vector.
+//! @relates BasicVector3D
+#ifndef SWIG
+template <class T, class U> inline auto operator*(const U a, const BasicVector3D<T>& v)
+{
+    return BasicVector3D<decltype(a * v.x())>(a * v.x(), a * v.y(), a * v.z());
+}
+#endif // USER_API
+
+// vector*vector not supported
+//    (We do not provide the operator form a*b of the dot product:
+//     Though nice to write, and in some cases perfectly justified,
+//     in general it tends to make expressions more difficult to read.)
+
+//! Division 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);
+}
+
+// =============================================================================
+// ?? for API generation ??
+// =============================================================================
+
+//! Returns dot product of (complex) vectors (antilinear in the first [=self] argument).
+#ifndef SWIG
+template <class T>
+template <class U>
+inline auto BasicVector3D<T>::dot(const BasicVector3D<U>& v) const
+{
+    BasicVector3D<T> left_star = this->conj();
+    return left_star.x() * v.x() + left_star.y() * v.y() + left_star.z() * v.z();
+}
+#endif // USER_API
+
+//! Returns cross product of (complex) vectors.
+#ifndef SWIG
+template <class T>
+template <class U>
+inline auto BasicVector3D<T>::cross(const BasicVector3D<U>& v) const
+{
+    return BasicVector3D<decltype(this->x() * v.x())>(
+        y() * v.z() - v.y() * z(), z() * v.x() - v.z() * x(), x() * v.y() - v.x() * y());
+}
+#endif // USER_API
+
+// -----------------------------------------------------------------------------
+// Functions of this (with no further argument)
+// -----------------------------------------------------------------------------
+
+//! Returns complex conjugate vector
+template <> inline R3 R3::conj() const
+{
+    return *this;
+}
+
+template <> inline C3 C3::conj() const
+{
+    return {std::conj(x()), std::conj(y()), std::conj(z())};
+}
+
+//! Returns azimuth angle.
+template <> inline double R3::phi() const
+{
+    return x() == 0.0 && y() == 0.0 ? 0.0 : std::atan2(-y(), x());
+}
+
+//! Returns polar angle.
+template <> inline double R3::theta() const
+{
+    return x() == 0.0 && y() == 0.0 && z() == 0.0 ? 0.0 : std::atan2(magxy(), z());
+}
+
+//! Returns cosine of polar angle.
+template <> inline double R3::cosTheta() const
+{
+    return mag() == 0 ? 1 : z() / mag();
+}
+
+//! Returns squared sine of polar angle.
+template <> inline double R3::sin2Theta() const
+{
+    return mag2() == 0 ? 0 : magxy2() / mag2();
+}
+
+//! Returns this, trivially converted to complex type.
+template <> inline C3 R3::complex() const
+{
+    return {x(), y(), z()};
+}
+
+//! Returns real parts.
+template <> inline R3 R3::real() const
+{
+    return *this;
+}
+
+template <> inline R3 C3::real() const
+{
+    return {x().real(), y().real(), z().real()};
+}
+
+//! Returns unit vector in direction of this. Throws for null vector.
+template <> inline R3 R3::unit() const
+{
+    double len = mag();
+    if (len == 0.0)
+        throw std::runtime_error("Cannot normalize zero vector");
+    return {x() / len, y() / len, z() / len};
+}
+
+template <> inline C3 C3::unit() const
+{
+    double len = mag();
+    if (len == 0.0)
+        throw std::runtime_error("Cannot normalize zero vector");
+    return {x() / len, y() / len, z() / len};
+}
+
+// -----------------------------------------------------------------------------
+// Combine two vectors
+// -----------------------------------------------------------------------------
+
+//! Returns angle with respect to another vector.
+template <> inline double R3::angle(const R3& v) const
+{
+    double cosa = 0;
+    double ptot = mag() * v.mag();
+    if (ptot > 0) {
+        cosa = dot(v) / ptot;
+        if (cosa > 1)
+            cosa = 1;
+        if (cosa < -1)
+            cosa = -1;
+    }
+    return std::acos(cosa);
+}
+
 #endif // BORNAGAIN_BASE_VECTOR_VECTORS3D_H
diff --git a/Wrap/Swig/fromBase.i b/Wrap/Swig/fromBase.i
index 41dc490de39..485e544ebfd 100644
--- a/Wrap/Swig/fromBase.i
+++ b/Wrap/Swig/fromBase.i
@@ -1,8 +1,7 @@
 %import(module="libBornAgainBase") "Base/Types/Complex.h"
+%import(module="libBornAgainBase") "Base/Vector/Vectors3D.h"
 %import(module="libBornAgainBase") "Base/Types/ICloneable.h"
-%import(module="libBornAgainBase") "Base/Vector/BasicVector3D.h"
 %import(module="libBornAgainBase") "Base/Vector/Transform3D.h"
-%import(module="libBornAgainBase") "Base/Vector/Vectors3D.h"
 %import(module="libBornAgainBase") "Base/Axis/IAxis.h"
 
 %template(R3) BasicVector3D<double>;
diff --git a/Wrap/Swig/libBornAgainBase.i b/Wrap/Swig/libBornAgainBase.i
index 4aade60c127..e684ef27f24 100644
--- a/Wrap/Swig/libBornAgainBase.i
+++ b/Wrap/Swig/libBornAgainBase.i
@@ -40,7 +40,6 @@
 
 %include "Base/Const/Units.h"
 
-%include "Base/Vector/BasicVector3D.h"
 %include "Base/Vector/Vectors3D.h"
 %include "Base/Vector/Direction.h"
 %include "Base/Vector/Transform3D.h"
diff --git a/Wrap/Swig/libBornAgainResample.i b/Wrap/Swig/libBornAgainResample.i
index 81f040a6e10..0ffdb74e878 100644
--- a/Wrap/Swig/libBornAgainResample.i
+++ b/Wrap/Swig/libBornAgainResample.i
@@ -45,7 +45,7 @@
 
 %{
 #include "BAVersion.h"
-#include "Base/Vector/BasicVector3D.h"
+#include "Base/Vector/Vectors3D.h"
 #include "Resample/Swig/MultiLayerFuncs.h"
 %}
 
diff --git a/auto/Wrap/doxygenBase.i b/auto/Wrap/doxygenBase.i
index 5ced3eb85a4..906b33e7c18 100644
--- a/auto/Wrap/doxygenBase.i
+++ b/auto/Wrap/doxygenBase.i
@@ -153,6 +153,146 @@ Returns result of rotation around z-axis.
 Returns result of rotation around the axis specified by another vector. 
 ";
 
+%feature("docstring")  BasicVector3D::BasicVector3D "BasicVector3D< T >::BasicVector3D()
+
+Constructs the null vector. 
+";
+
+%feature("docstring")  BasicVector3D::BasicVector3D "BasicVector3D< T >::BasicVector3D(const T x, const T y, const T z)
+
+Constructs a vector from cartesian components. 
+";
+
+%feature("docstring")  BasicVector3D::x "T BasicVector3D< T >::x() const
+
+Returns x-component in cartesian coordinate system. 
+";
+
+%feature("docstring")  BasicVector3D::y "T BasicVector3D< T >::y() const
+
+Returns y-component in cartesian coordinate system. 
+";
+
+%feature("docstring")  BasicVector3D::z "T BasicVector3D< T >::z() const
+
+Returns z-component in cartesian coordinate system. 
+";
+
+%feature("docstring")  BasicVector3D::setX "void BasicVector3D< T >::setX(const T &a)
+
+Sets x-component in cartesian coordinate system. 
+";
+
+%feature("docstring")  BasicVector3D::setY "void BasicVector3D< T >::setY(const T &a)
+
+Sets y-component in cartesian coordinate system. 
+";
+
+%feature("docstring")  BasicVector3D::setZ "void BasicVector3D< T >::setZ(const T &a)
+
+Sets z-component in cartesian coordinate system. 
+";
+
+%feature("docstring")  BasicVector3D::conj "BasicVector3D<T> BasicVector3D< T >::conj() const
+
+Returns complex conjugate vector. 
+";
+
+%feature("docstring")  BasicVector3D::mag2 "double BasicVector3D< T >::mag2() const
+
+Returns magnitude squared of the vector. 
+";
+
+%feature("docstring")  BasicVector3D::mag "double BasicVector3D< T >::mag() const
+
+Returns magnitude of the vector. 
+";
+
+%feature("docstring")  BasicVector3D::magxy2 "double BasicVector3D< T >::magxy2() const
+
+Returns squared distance from z axis. 
+";
+
+%feature("docstring")  BasicVector3D::magxy "double BasicVector3D< T >::magxy() const
+
+Returns distance from z axis. 
+";
+
+%feature("docstring")  BasicVector3D::phi "double BasicVector3D< T >::phi() const
+
+Returns azimuth angle. 
+";
+
+%feature("docstring")  BasicVector3D::theta "double BasicVector3D< T >::theta() const
+
+Returns polar angle. 
+";
+
+%feature("docstring")  BasicVector3D::cosTheta "double BasicVector3D< T >::cosTheta() const
+
+Returns cosine of polar angle. 
+";
+
+%feature("docstring")  BasicVector3D::sin2Theta "double BasicVector3D< T >::sin2Theta() const
+
+Returns squared sine of polar angle. 
+";
+
+%feature("docstring")  BasicVector3D::unit "BasicVector3D<T> BasicVector3D< T >::unit() const
+
+Returns unit vector in direction of this. Throws for null vector. 
+";
+
+%feature("docstring")  BasicVector3D::complex "C3 BasicVector3D< T >::complex() const
+
+Returns this, trivially converted to complex type. 
+";
+
+%feature("docstring")  BasicVector3D::real "R3 BasicVector3D< T >::real() const
+
+Returns real parts. 
+";
+
+%feature("docstring")  BasicVector3D::dot "auto BasicVector3D< T >::dot(const BasicVector3D< U > &v) const
+
+Returns dot product of vectors (antilinear in the first [=self] argument). 
+";
+
+%feature("docstring")  BasicVector3D::cross "auto BasicVector3D< T >::cross(const BasicVector3D< U > &v) const
+
+Returns cross product of vectors (linear in both arguments). 
+";
+
+%feature("docstring")  BasicVector3D::angle "double BasicVector3D< T >::angle(const BasicVector3D< T > &v) const
+
+Returns angle with respect to another vector. 
+";
+
+%feature("docstring")  BasicVector3D::project "BasicVector3D<T> BasicVector3D< T >::project(const BasicVector3D< T > &v) const
+
+Returns projection of this onto other vector: (this*v)*v/|v|^2. 
+";
+
+%feature("docstring")  BasicVector3D::rotatedX "BasicVector3D<T> BasicVector3D< T >::rotatedX(double a) const
+
+Returns result of rotation around x-axis. 
+";
+
+%feature("docstring")  BasicVector3D::rotatedY "BasicVector3D<T> BasicVector3D< T >::rotatedY(double a) const
+
+Returns result of rotation around y-axis. 
+";
+
+%feature("docstring")  BasicVector3D::rotatedZ "BasicVector3D<T> BasicVector3D< T >::rotatedZ(double a) const
+
+Returns result of rotation around z-axis. 
+";
+
+%feature("docstring")  BasicVector3D::rotated "BasicVector3D<T> BasicVector3D< T >::rotated(double a, const BasicVector3D< T > &v) const
+
+Returns result of rotation around the axis specified by another vector. 
+";
+
 
 // File: structBin1D.xml
 %feature("docstring") Bin1D "";
@@ -1871,9 +2011,6 @@ This templated function is used in catalogs in form of a function pointer 'creat
 // File: ThreadInfo_8h.xml
 
 
-// File: BasicVector3D_8cpp.xml
-
-
 // File: BasicVector3D_8h.xml
 
 
diff --git a/auto/Wrap/libBornAgainBase.py b/auto/Wrap/libBornAgainBase.py
index dc209c142f3..dcb3f79a76c 100644
--- a/auto/Wrap/libBornAgainBase.py
+++ b/auto/Wrap/libBornAgainBase.py
@@ -3189,7 +3189,7 @@ class R3(arrayR3_t):
     def complex(self):
         r"""
         complex(R3 self) -> C3
-        BasicVector3D<complex_t> BasicVector3D< T >::complex() const
+        C3 BasicVector3D< T >::complex() const
 
         Returns this, trivially converted to complex type. 
 
@@ -3199,7 +3199,7 @@ class R3(arrayR3_t):
     def real(self):
         r"""
         real(R3 self) -> R3
-        BasicVector3D<double> BasicVector3D< T >::real() const
+        R3 BasicVector3D< T >::real() const
 
         Returns real parts. 
 
@@ -3552,7 +3552,7 @@ class C3(arrayC3_t):
     def real(self):
         r"""
         real(C3 self) -> R3
-        BasicVector3D<double> BasicVector3D< T >::real() const
+        R3 BasicVector3D< T >::real() const
 
         Returns real parts. 
 
diff --git a/auto/Wrap/libBornAgainBase_wrap.cpp b/auto/Wrap/libBornAgainBase_wrap.cpp
index a4538137546..56a6a683ce3 100644
--- a/auto/Wrap/libBornAgainBase_wrap.cpp
+++ b/auto/Wrap/libBornAgainBase_wrap.cpp
@@ -30862,7 +30862,7 @@ SWIGINTERN PyObject *_wrap_R3_complex(PyObject *SWIGUNUSEDPARM(self), PyObject *
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
-  BasicVector3D< complex_t > result;
+  C3 result;
   
   if (!args) SWIG_fail;
   swig_obj[0] = args;
@@ -30872,7 +30872,7 @@ SWIGINTERN PyObject *_wrap_R3_complex(PyObject *SWIGUNUSEDPARM(self), PyObject *
   }
   arg1 = reinterpret_cast< BasicVector3D< double > * >(argp1);
   result = ((BasicVector3D< double > const *)arg1)->complex();
-  resultobj = SWIG_NewPointerObj((new BasicVector3D< complex_t >(static_cast< const BasicVector3D< complex_t >& >(result))), SWIGTYPE_p_BasicVector3DT_std__complexT_double_t_t, SWIG_POINTER_OWN |  0 );
+  resultobj = SWIG_NewPointerObj((new C3(static_cast< const C3& >(result))), SWIGTYPE_p_BasicVector3DT_std__complexT_double_t_t, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
   return NULL;
@@ -30885,7 +30885,7 @@ SWIGINTERN PyObject *_wrap_R3_real(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
-  BasicVector3D< double > result;
+  R3 result;
   
   if (!args) SWIG_fail;
   swig_obj[0] = args;
@@ -30895,7 +30895,7 @@ SWIGINTERN PyObject *_wrap_R3_real(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
   }
   arg1 = reinterpret_cast< BasicVector3D< double > * >(argp1);
   result = ((BasicVector3D< double > const *)arg1)->real();
-  resultobj = SWIG_NewPointerObj((new BasicVector3D< double >(static_cast< const BasicVector3D< double >& >(result))), SWIGTYPE_p_BasicVector3DT_double_t, SWIG_POINTER_OWN |  0 );
+  resultobj = SWIG_NewPointerObj((new R3(static_cast< const R3& >(result))), SWIGTYPE_p_BasicVector3DT_double_t, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
   return NULL;
@@ -33288,7 +33288,7 @@ SWIGINTERN PyObject *_wrap_C3_real(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
-  BasicVector3D< double > result;
+  R3 result;
   
   if (!args) SWIG_fail;
   swig_obj[0] = args;
@@ -33298,7 +33298,7 @@ SWIGINTERN PyObject *_wrap_C3_real(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
   }
   arg1 = reinterpret_cast< BasicVector3D< std::complex< double > > * >(argp1);
   result = ((BasicVector3D< std::complex< double > > const *)arg1)->real();
-  resultobj = SWIG_NewPointerObj((new BasicVector3D< double >(static_cast< const BasicVector3D< double >& >(result))), SWIGTYPE_p_BasicVector3DT_double_t, SWIG_POINTER_OWN |  0 );
+  resultobj = SWIG_NewPointerObj((new R3(static_cast< const R3& >(result))), SWIGTYPE_p_BasicVector3DT_double_t, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
   return NULL;
@@ -36622,14 +36622,14 @@ static PyMethodDef SwigMethods[] = {
 		""},
 	 { "R3_complex", _wrap_R3_complex, METH_O, "\n"
 		"R3_complex(R3 self) -> C3\n"
-		"BasicVector3D<complex_t> BasicVector3D< T >::complex() const\n"
+		"C3 BasicVector3D< T >::complex() const\n"
 		"\n"
 		"Returns this, trivially converted to complex type. \n"
 		"\n"
 		""},
 	 { "R3_real", _wrap_R3_real, METH_O, "\n"
 		"R3_real(R3 self) -> R3\n"
-		"BasicVector3D<double> BasicVector3D< T >::real() const\n"
+		"R3 BasicVector3D< T >::real() const\n"
 		"\n"
 		"Returns real parts. \n"
 		"\n"
@@ -36809,7 +36809,7 @@ static PyMethodDef SwigMethods[] = {
 		""},
 	 { "C3_real", _wrap_C3_real, METH_O, "\n"
 		"C3_real(C3 self) -> R3\n"
-		"BasicVector3D<double> BasicVector3D< T >::real() const\n"
+		"R3 BasicVector3D< T >::real() const\n"
 		"\n"
 		"Returns real parts. \n"
 		"\n"
@@ -36922,7 +36922,7 @@ static void *_p_BasicVector3DT_double_tTo_p_std__arrayT_double_3_t(void *x, int
 }
 static swig_type_info _swigt__p_BasicVector3DT_double_t = {"_p_BasicVector3DT_double_t", "std::vector< BasicVector3D< double > >::value_type *|R3 *|BasicVector3D< double > *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_BasicVector3DT_int_t = {"_p_BasicVector3DT_int_t", "I3 *|BasicVector3D< int > *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_BasicVector3DT_std__complexT_double_t_t = {"_p_BasicVector3DT_std__complexT_double_t_t", "BasicVector3D< std::complex< double > > *|std::vector< BasicVector3D< std::complex< double > > >::value_type *|C3 *|BasicVector3D< complex_t > *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_BasicVector3DT_std__complexT_double_t_t = {"_p_BasicVector3DT_std__complexT_double_t_t", "BasicVector3D< std::complex< double > > *|std::vector< BasicVector3D< std::complex< double > > >::value_type *|C3 *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Bin1D = {"_p_Bin1D", "Bin1D *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Bin1DCVector = {"_p_Bin1DCVector", "Bin1DCVector *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Bin1DKVector = {"_p_Bin1DKVector", "Bin1DKVector *", 0, 0, (void*)0, 0};
diff --git a/auto/Wrap/libBornAgainCore_wrap.cpp b/auto/Wrap/libBornAgainCore_wrap.cpp
index 667db20c227..63d0a224cc5 100644
--- a/auto/Wrap/libBornAgainCore_wrap.cpp
+++ b/auto/Wrap/libBornAgainCore_wrap.cpp
@@ -27498,7 +27498,7 @@ SWIGINTERN PyObject *_wrap_R3_complex(PyObject *SWIGUNUSEDPARM(self), PyObject *
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
-  BasicVector3D< complex_t > result;
+  C3 result;
   
   if (!args) SWIG_fail;
   swig_obj[0] = args;
@@ -27508,7 +27508,7 @@ SWIGINTERN PyObject *_wrap_R3_complex(PyObject *SWIGUNUSEDPARM(self), PyObject *
   }
   arg1 = reinterpret_cast< BasicVector3D< double > * >(argp1);
   result = ((BasicVector3D< double > const *)arg1)->complex();
-  resultobj = SWIG_NewPointerObj((new BasicVector3D< complex_t >(static_cast< const BasicVector3D< complex_t >& >(result))), SWIGTYPE_p_BasicVector3DT_std__complexT_double_t_t, SWIG_POINTER_OWN |  0 );
+  resultobj = SWIG_NewPointerObj((new C3(static_cast< const C3& >(result))), SWIGTYPE_p_BasicVector3DT_std__complexT_double_t_t, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
   return NULL;
@@ -27521,7 +27521,7 @@ SWIGINTERN PyObject *_wrap_R3_real(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
-  BasicVector3D< double > result;
+  R3 result;
   
   if (!args) SWIG_fail;
   swig_obj[0] = args;
@@ -27531,7 +27531,7 @@ SWIGINTERN PyObject *_wrap_R3_real(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
   }
   arg1 = reinterpret_cast< BasicVector3D< double > * >(argp1);
   result = ((BasicVector3D< double > const *)arg1)->real();
-  resultobj = SWIG_NewPointerObj((new BasicVector3D< double >(static_cast< const BasicVector3D< double >& >(result))), SWIGTYPE_p_BasicVector3DT_double_t, SWIG_POINTER_OWN |  0 );
+  resultobj = SWIG_NewPointerObj((new R3(static_cast< const R3& >(result))), SWIGTYPE_p_BasicVector3DT_double_t, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
   return NULL;
@@ -30048,7 +30048,7 @@ SWIGINTERN PyObject *_wrap_C3_real(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
-  BasicVector3D< double > result;
+  R3 result;
   
   if (!args) SWIG_fail;
   swig_obj[0] = args;
@@ -30058,7 +30058,7 @@ SWIGINTERN PyObject *_wrap_C3_real(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
   }
   arg1 = reinterpret_cast< BasicVector3D< std::complex< double > > * >(argp1);
   result = ((BasicVector3D< std::complex< double > > const *)arg1)->real();
-  resultobj = SWIG_NewPointerObj((new BasicVector3D< double >(static_cast< const BasicVector3D< double >& >(result))), SWIGTYPE_p_BasicVector3DT_double_t, SWIG_POINTER_OWN |  0 );
+  resultobj = SWIG_NewPointerObj((new R3(static_cast< const R3& >(result))), SWIGTYPE_p_BasicVector3DT_double_t, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
   return NULL;
@@ -47982,7 +47982,7 @@ static swig_type_info _swigt__p_AlphaScan = {"_p_AlphaScan", "AlphaScan *", 0, 0
 static swig_type_info _swigt__p_AxisInfo = {"_p_AxisInfo", "std::vector< AxisInfo >::value_type *|AxisInfo *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_BasicVector3DT_double_t = {"_p_BasicVector3DT_double_t", "std::vector< BasicVector3D< double > >::value_type *|R3 *|BasicVector3D< double > *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_BasicVector3DT_int_t = {"_p_BasicVector3DT_int_t", "I3 *|BasicVector3D< int > *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_BasicVector3DT_std__complexT_double_t_t = {"_p_BasicVector3DT_std__complexT_double_t_t", "BasicVector3D< std::complex< double > > *|std::vector< BasicVector3D< std::complex< double > > >::value_type *|C3 *|BasicVector3D< complex_t > *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_BasicVector3DT_std__complexT_double_t_t = {"_p_BasicVector3DT_std__complexT_double_t_t", "BasicVector3D< std::complex< double > > *|std::vector< BasicVector3D< std::complex< double > > >::value_type *|C3 *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Beam = {"_p_Beam", "Beam *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_ChiSquaredModule = {"_p_ChiSquaredModule", "ChiSquaredModule *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_ConstantBackground = {"_p_ConstantBackground", "ConstantBackground *", 0, 0, (void*)0, 0};
diff --git a/auto/Wrap/libBornAgainDevice_wrap.cpp b/auto/Wrap/libBornAgainDevice_wrap.cpp
index d7b42fa5b67..7a0eb6b5b19 100644
--- a/auto/Wrap/libBornAgainDevice_wrap.cpp
+++ b/auto/Wrap/libBornAgainDevice_wrap.cpp
@@ -27016,7 +27016,7 @@ SWIGINTERN PyObject *_wrap_R3_complex(PyObject *SWIGUNUSEDPARM(self), PyObject *
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
-  BasicVector3D< complex_t > result;
+  C3 result;
   
   if (!args) SWIG_fail;
   swig_obj[0] = args;
@@ -27026,7 +27026,7 @@ SWIGINTERN PyObject *_wrap_R3_complex(PyObject *SWIGUNUSEDPARM(self), PyObject *
   }
   arg1 = reinterpret_cast< BasicVector3D< double > * >(argp1);
   result = ((BasicVector3D< double > const *)arg1)->complex();
-  resultobj = SWIG_NewPointerObj((new BasicVector3D< complex_t >(static_cast< const BasicVector3D< complex_t >& >(result))), SWIGTYPE_p_BasicVector3DT_std__complexT_double_t_t, SWIG_POINTER_OWN |  0 );
+  resultobj = SWIG_NewPointerObj((new C3(static_cast< const C3& >(result))), SWIGTYPE_p_BasicVector3DT_std__complexT_double_t_t, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
   return NULL;
@@ -27039,7 +27039,7 @@ SWIGINTERN PyObject *_wrap_R3_real(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
-  BasicVector3D< double > result;
+  R3 result;
   
   if (!args) SWIG_fail;
   swig_obj[0] = args;
@@ -27049,7 +27049,7 @@ SWIGINTERN PyObject *_wrap_R3_real(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
   }
   arg1 = reinterpret_cast< BasicVector3D< double > * >(argp1);
   result = ((BasicVector3D< double > const *)arg1)->real();
-  resultobj = SWIG_NewPointerObj((new BasicVector3D< double >(static_cast< const BasicVector3D< double >& >(result))), SWIGTYPE_p_BasicVector3DT_double_t, SWIG_POINTER_OWN |  0 );
+  resultobj = SWIG_NewPointerObj((new R3(static_cast< const R3& >(result))), SWIGTYPE_p_BasicVector3DT_double_t, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
   return NULL;
@@ -29442,7 +29442,7 @@ SWIGINTERN PyObject *_wrap_C3_real(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
-  BasicVector3D< double > result;
+  R3 result;
   
   if (!args) SWIG_fail;
   swig_obj[0] = args;
@@ -29452,7 +29452,7 @@ SWIGINTERN PyObject *_wrap_C3_real(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
   }
   arg1 = reinterpret_cast< BasicVector3D< std::complex< double > > * >(argp1);
   result = ((BasicVector3D< std::complex< double > > const *)arg1)->real();
-  resultobj = SWIG_NewPointerObj((new BasicVector3D< double >(static_cast< const BasicVector3D< double >& >(result))), SWIGTYPE_p_BasicVector3DT_double_t, SWIG_POINTER_OWN |  0 );
+  resultobj = SWIG_NewPointerObj((new R3(static_cast< const R3& >(result))), SWIGTYPE_p_BasicVector3DT_double_t, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
   return NULL;
@@ -49695,7 +49695,7 @@ static swig_type_info _swigt__p_Axes = {"_p_Axes", "Axes *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_AxisInfo = {"_p_AxisInfo", "AxisInfo *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_BasicVector3DT_double_t = {"_p_BasicVector3DT_double_t", "std::vector< BasicVector3D< double > >::value_type *|R3 *|BasicVector3D< double > *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_BasicVector3DT_int_t = {"_p_BasicVector3DT_int_t", "I3 *|BasicVector3D< int > *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_BasicVector3DT_std__complexT_double_t_t = {"_p_BasicVector3DT_std__complexT_double_t_t", "BasicVector3D< std::complex< double > > *|std::vector< BasicVector3D< std::complex< double > > >::value_type *|C3 *|BasicVector3D< complex_t > *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_BasicVector3DT_std__complexT_double_t_t = {"_p_BasicVector3DT_std__complexT_double_t_t", "BasicVector3D< std::complex< double > > *|std::vector< BasicVector3D< std::complex< double > > >::value_type *|C3 *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Beam = {"_p_Beam", "Beam *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Bin1D = {"_p_Bin1D", "Bin1D *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_CloneableVectorT_IAxis_t = {"_p_CloneableVectorT_IAxis_t", "CloneableVector< IAxis > *", 0, 0, (void*)0, 0};
diff --git a/auto/Wrap/libBornAgainResample_wrap.cpp b/auto/Wrap/libBornAgainResample_wrap.cpp
index a7f50c93914..9f0f8ff7604 100644
--- a/auto/Wrap/libBornAgainResample_wrap.cpp
+++ b/auto/Wrap/libBornAgainResample_wrap.cpp
@@ -6926,7 +6926,7 @@ SWIGINTERNINLINE PyObject*
 
 
 #include "BAVersion.h"
-#include "Base/Vector/BasicVector3D.h"
+#include "Base/Vector/Vectors3D.h"
 #include "Resample/Swig/MultiLayerFuncs.h"
 
 SWIGINTERN BasicVector3D< double > BasicVector3D_Sl_double_Sg____add__(BasicVector3D< double > const *self,BasicVector3D< double > const &rhs){
@@ -27459,7 +27459,7 @@ SWIGINTERN PyObject *_wrap_R3_complex(PyObject *SWIGUNUSEDPARM(self), PyObject *
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
-  BasicVector3D< complex_t > result;
+  C3 result;
   
   if (!args) SWIG_fail;
   swig_obj[0] = args;
@@ -27469,7 +27469,7 @@ SWIGINTERN PyObject *_wrap_R3_complex(PyObject *SWIGUNUSEDPARM(self), PyObject *
   }
   arg1 = reinterpret_cast< BasicVector3D< double > * >(argp1);
   result = ((BasicVector3D< double > const *)arg1)->complex();
-  resultobj = SWIG_NewPointerObj((new BasicVector3D< complex_t >(static_cast< const BasicVector3D< complex_t >& >(result))), SWIGTYPE_p_BasicVector3DT_std__complexT_double_t_t, SWIG_POINTER_OWN |  0 );
+  resultobj = SWIG_NewPointerObj((new C3(static_cast< const C3& >(result))), SWIGTYPE_p_BasicVector3DT_std__complexT_double_t_t, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
   return NULL;
@@ -27482,7 +27482,7 @@ SWIGINTERN PyObject *_wrap_R3_real(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
-  BasicVector3D< double > result;
+  R3 result;
   
   if (!args) SWIG_fail;
   swig_obj[0] = args;
@@ -27492,7 +27492,7 @@ SWIGINTERN PyObject *_wrap_R3_real(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
   }
   arg1 = reinterpret_cast< BasicVector3D< double > * >(argp1);
   result = ((BasicVector3D< double > const *)arg1)->real();
-  resultobj = SWIG_NewPointerObj((new BasicVector3D< double >(static_cast< const BasicVector3D< double >& >(result))), SWIGTYPE_p_BasicVector3DT_double_t, SWIG_POINTER_OWN |  0 );
+  resultobj = SWIG_NewPointerObj((new R3(static_cast< const R3& >(result))), SWIGTYPE_p_BasicVector3DT_double_t, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
   return NULL;
@@ -30009,7 +30009,7 @@ SWIGINTERN PyObject *_wrap_C3_real(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
-  BasicVector3D< double > result;
+  R3 result;
   
   if (!args) SWIG_fail;
   swig_obj[0] = args;
@@ -30019,7 +30019,7 @@ SWIGINTERN PyObject *_wrap_C3_real(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
   }
   arg1 = reinterpret_cast< BasicVector3D< std::complex< double > > * >(argp1);
   result = ((BasicVector3D< std::complex< double > > const *)arg1)->real();
-  resultobj = SWIG_NewPointerObj((new BasicVector3D< double >(static_cast< const BasicVector3D< double >& >(result))), SWIGTYPE_p_BasicVector3DT_double_t, SWIG_POINTER_OWN |  0 );
+  resultobj = SWIG_NewPointerObj((new R3(static_cast< const R3& >(result))), SWIGTYPE_p_BasicVector3DT_double_t, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
   return NULL;
@@ -33106,7 +33106,7 @@ static void *_p_BasicVector3DT_double_tTo_p_std__arrayT_double_3_t(void *x, int
 }
 static swig_type_info _swigt__p_BasicVector3DT_double_t = {"_p_BasicVector3DT_double_t", "std::vector< BasicVector3D< double > >::value_type *|R3 *|BasicVector3D< double > *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_BasicVector3DT_int_t = {"_p_BasicVector3DT_int_t", "I3 *|BasicVector3D< int > *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_BasicVector3DT_std__complexT_double_t_t = {"_p_BasicVector3DT_std__complexT_double_t_t", "BasicVector3D< std::complex< double > > *|std::vector< BasicVector3D< std::complex< double > > >::value_type *|C3 *|BasicVector3D< complex_t > *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_BasicVector3DT_std__complexT_double_t_t = {"_p_BasicVector3DT_std__complexT_double_t_t", "BasicVector3D< std::complex< double > > *|std::vector< BasicVector3D< std::complex< double > > >::value_type *|C3 *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_MultiLayer = {"_p_MultiLayer", "MultiLayer *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_SimulationOptions = {"_p_SimulationOptions", "SimulationOptions *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_ThreadInfo = {"_p_ThreadInfo", "ThreadInfo *", 0, 0, (void*)0, 0};
diff --git a/auto/Wrap/libBornAgainSample_wrap.cpp b/auto/Wrap/libBornAgainSample_wrap.cpp
index ead957e0f0e..a0167d15d6e 100644
--- a/auto/Wrap/libBornAgainSample_wrap.cpp
+++ b/auto/Wrap/libBornAgainSample_wrap.cpp
@@ -28673,7 +28673,7 @@ SWIGINTERN PyObject *_wrap_R3_complex(PyObject *SWIGUNUSEDPARM(self), PyObject *
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
-  BasicVector3D< complex_t > result;
+  C3 result;
   
   if (!args) SWIG_fail;
   swig_obj[0] = args;
@@ -28683,7 +28683,7 @@ SWIGINTERN PyObject *_wrap_R3_complex(PyObject *SWIGUNUSEDPARM(self), PyObject *
   }
   arg1 = reinterpret_cast< BasicVector3D< double > * >(argp1);
   result = ((BasicVector3D< double > const *)arg1)->complex();
-  resultobj = SWIG_NewPointerObj((new BasicVector3D< complex_t >(static_cast< const BasicVector3D< complex_t >& >(result))), SWIGTYPE_p_BasicVector3DT_std__complexT_double_t_t, SWIG_POINTER_OWN |  0 );
+  resultobj = SWIG_NewPointerObj((new C3(static_cast< const C3& >(result))), SWIGTYPE_p_BasicVector3DT_std__complexT_double_t_t, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
   return NULL;
@@ -28696,7 +28696,7 @@ SWIGINTERN PyObject *_wrap_R3_real(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
-  BasicVector3D< double > result;
+  R3 result;
   
   if (!args) SWIG_fail;
   swig_obj[0] = args;
@@ -28706,7 +28706,7 @@ SWIGINTERN PyObject *_wrap_R3_real(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
   }
   arg1 = reinterpret_cast< BasicVector3D< double > * >(argp1);
   result = ((BasicVector3D< double > const *)arg1)->real();
-  resultobj = SWIG_NewPointerObj((new BasicVector3D< double >(static_cast< const BasicVector3D< double >& >(result))), SWIGTYPE_p_BasicVector3DT_double_t, SWIG_POINTER_OWN |  0 );
+  resultobj = SWIG_NewPointerObj((new R3(static_cast< const R3& >(result))), SWIGTYPE_p_BasicVector3DT_double_t, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
   return NULL;
@@ -31223,7 +31223,7 @@ SWIGINTERN PyObject *_wrap_C3_real(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
-  BasicVector3D< double > result;
+  R3 result;
   
   if (!args) SWIG_fail;
   swig_obj[0] = args;
@@ -31233,7 +31233,7 @@ SWIGINTERN PyObject *_wrap_C3_real(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
   }
   arg1 = reinterpret_cast< BasicVector3D< std::complex< double > > * >(argp1);
   result = ((BasicVector3D< std::complex< double > > const *)arg1)->real();
-  resultobj = SWIG_NewPointerObj((new BasicVector3D< double >(static_cast< const BasicVector3D< double >& >(result))), SWIGTYPE_p_BasicVector3DT_double_t, SWIG_POINTER_OWN |  0 );
+  resultobj = SWIG_NewPointerObj((new R3(static_cast< const R3& >(result))), SWIGTYPE_p_BasicVector3DT_double_t, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
   return NULL;
@@ -78425,7 +78425,7 @@ static swig_type_info _swigt__p_Admixtures = {"_p_Admixtures", "Admixtures *", 0
 static swig_type_info _swigt__p_BasicLattice2D = {"_p_BasicLattice2D", "BasicLattice2D *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_BasicVector3DT_double_t = {"_p_BasicVector3DT_double_t", "std::vector< BasicVector3D< double > >::value_type *|R3 *|BasicVector3D< double > *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_BasicVector3DT_int_t = {"_p_BasicVector3DT_int_t", "I3 *|BasicVector3D< int > *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_BasicVector3DT_std__complexT_double_t_t = {"_p_BasicVector3DT_std__complexT_double_t_t", "BasicVector3D< std::complex< double > > *|std::vector< BasicVector3D< std::complex< double > > >::value_type *|C3 *|BasicVector3D< complex_t > *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_BasicVector3DT_std__complexT_double_t_t = {"_p_BasicVector3DT_std__complexT_double_t_t", "BasicVector3D< std::complex< double > > *|std::vector< BasicVector3D< std::complex< double > > >::value_type *|C3 *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Crystal = {"_p_Crystal", "Crystal *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_FTDecayFunction1DCauchy = {"_p_FTDecayFunction1DCauchy", "FTDecayFunction1DCauchy *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_FTDecayFunction1DGauss = {"_p_FTDecayFunction1DGauss", "FTDecayFunction1DGauss *", 0, 0, (void*)0, 0};
-- 
GitLab