Skip to content
Snippets Groups Projects
Select Git revision
  • 0a24f6aeac3501e32b330be1edc150d76049c71f
  • develop default protected
  • feature/variational-hydro
  • origin/stage/bouguettaia
  • feature/gmsh-reader
  • feature/reconstruction
  • save_clemence
  • feature/kinetic-schemes
  • feature/local-dt-fsi
  • feature/composite-scheme-sources
  • feature/composite-scheme-other-fluxes
  • feature/serraille
  • feature/composite-scheme
  • hyperplastic
  • feature/polynomials
  • feature/gks
  • feature/implicit-solver-o2
  • feature/coupling_module
  • feature/implicit-solver
  • feature/merge-local-dt-fsi
  • master protected
  • v0.5.0 protected
  • v0.4.1 protected
  • v0.4.0 protected
  • v0.3.0 protected
  • v0.2.0 protected
  • v0.1.0 protected
  • Kidder
  • v0.0.4 protected
  • v0.0.3 protected
  • v0.0.2 protected
  • v0 protected
  • v0.0.1 protected
33 results

Vector.hpp

Blame
  • TinyMatrix.hpp 11.44 KiB
    #ifndef TINY_MATRIX_HPP
    #define TINY_MATRIX_HPP
    
    #include <utils/PugsAssert.hpp>
    #include <utils/PugsMacros.hpp>
    
    #include <utils/Types.hpp>
    
    #include <algebra/TinyVector.hpp>
    
    #include <iostream>
    
    template <size_t N, typename T = double>
    class TinyMatrix
    {
     public:
      using data_type = T;
    
     private:
      T m_values[N * N];
      static_assert((N > 0), "TinyMatrix size must be strictly positive");
    
      PUGS_FORCEINLINE
      constexpr size_t
      _index(size_t i, size_t j) const noexcept   // LCOV_EXCL_LINE (due to forced inline)
      {
        return i * N + j;
      }
    
      template <typename... Args>
      PUGS_FORCEINLINE constexpr void
      _unpackVariadicInput(const T& t, Args&&... args) noexcept
      {
        m_values[N * N - 1 - sizeof...(args)] = t;
        if constexpr (sizeof...(args) > 0) {
          this->_unpackVariadicInput(std::forward<Args>(args)...);
        }
      }
    
     public:
      PUGS_INLINE
      constexpr TinyMatrix
      operator-() const
      {
        TinyMatrix opposed;
        for (size_t i = 0; i < N * N; ++i) {
          opposed.m_values[i] = -m_values[i];
        }
        return opposed;
      }
    
      PUGS_INLINE
      constexpr friend TinyMatrix
      operator*(const T& t, const TinyMatrix& A)
      {
        TinyMatrix B = A;
        return B *= t;
      }
    
      PUGS_INLINE
      constexpr friend TinyMatrix
      operator*(const T& t, TinyMatrix&& A)
      {
        return std::move(A *= t);
      }
    
      PUGS_INLINE
      constexpr TinyMatrix&
      operator*=(const T& t)
      {
        for (size_t i = 0; i < N * N; ++i) {
          m_values[i] *= t;
        }
        return *this;
      }
    
      PUGS_INLINE
      constexpr TinyMatrix
      operator*(const TinyMatrix& B) const
      {
        const TinyMatrix& A = *this;
        TinyMatrix AB;
        for (size_t i = 0; i < N; ++i) {
          for (size_t j = 0; j < N; ++j) {
            T sum = A(i, 0) * B(0, j);
            for (size_t k = 1; k < N; ++k) {
              sum += A(i, k) * B(k, j);
            }
            AB(i, j) = sum;
          }
        }
        return AB;
      }
    
      PUGS_INLINE
      constexpr TinyVector<N, T>
      operator*(const TinyVector<N, T>& x) const
      {
        const TinyMatrix& A = *this;
        TinyVector<N, T> Ax;
        for (size_t i = 0; i < N; ++i) {
          T sum = A(i, 0) * x[0];
          for (size_t j = 1; j < N; ++j) {
            sum += A(i, j) * x[j];
          }
          Ax[i] = sum;
        }
        return Ax;
      }
    
      PUGS_INLINE
      constexpr friend std::ostream&
      operator<<(std::ostream& os, const TinyMatrix& A)
      {
        if constexpr (N == 1) {
          os << A(0, 0);
        } else {
          os << '[';
          for (size_t i = 0; i < N; ++i) {
            os << '(' << A(i, 0);
            for (size_t j = 1; j < N; ++j) {
              os << ',' << A(i, j);
            }
            os << ')';
          }
          os << ']';
        }
        return os;
      }
    
      PUGS_INLINE
      constexpr bool
      operator==(const TinyMatrix& A) const
      {
        for (size_t i = 0; i < N * N; ++i) {
          if (m_values[i] != A.m_values[i])
            return false;
        }
        return true;
      }
    
      PUGS_INLINE
      constexpr bool
      operator!=(const TinyMatrix& A) const
      {
        return not this->operator==(A);
      }
    
      PUGS_INLINE
      constexpr TinyMatrix
      operator+(const TinyMatrix& A) const
      {
        TinyMatrix sum;
        for (size_t i = 0; i < N * N; ++i) {
          sum.m_values[i] = m_values[i] + A.m_values[i];
        }
        return sum;
      }
    
      PUGS_INLINE
      constexpr TinyMatrix
      operator+(TinyMatrix&& A) const
      {
        for (size_t i = 0; i < N * N; ++i) {
          A.m_values[i] += m_values[i];
        }
        return std::move(A);
      }
    
      PUGS_INLINE
      constexpr TinyMatrix
      operator-(const TinyMatrix& A) const
      {
        TinyMatrix difference;
        for (size_t i = 0; i < N * N; ++i) {
          difference.m_values[i] = m_values[i] - A.m_values[i];
        }
        return difference;
      }
    
      PUGS_INLINE
      constexpr TinyMatrix
      operator-(TinyMatrix&& A) const
      {
        for (size_t i = 0; i < N * N; ++i) {
          A.m_values[i] = m_values[i] - A.m_values[i];
        }
        return std::move(A);
      }
    
      PUGS_INLINE
      constexpr TinyMatrix&
      operator+=(const TinyMatrix& A)
      {
        for (size_t i = 0; i < N * N; ++i) {
          m_values[i] += A.m_values[i];
        }
        return *this;
      }
    
      PUGS_INLINE
      constexpr void
      operator+=(const volatile TinyMatrix& A) volatile
      {
        for (size_t i = 0; i < N * N; ++i) {
          m_values[i] += A.m_values[i];
        }
      }
    
      PUGS_INLINE
      constexpr TinyMatrix&
      operator-=(const TinyMatrix& A)
      {
        for (size_t i = 0; i < N * N; ++i) {
          m_values[i] -= A.m_values[i];
        }
        return *this;
      }
    
      PUGS_INLINE
      constexpr T&
      operator()(size_t i, size_t j) noexcept(NO_ASSERT)
      {
        Assert((i < N) and (j < N));
        return m_values[_index(i, j)];
      }
    
      PUGS_INLINE
      constexpr const T&
      operator()(size_t i, size_t j) const noexcept(NO_ASSERT)
      {
        Assert((i < N) and (j < N));
        return m_values[_index(i, j)];
      }
    
      PUGS_INLINE
      constexpr TinyMatrix& operator=(ZeroType) noexcept
      {
        static_assert(std::is_arithmetic<T>(), "Cannot assign 'zero' value for non-arithmetic types");
        for (size_t i = 0; i < N * N; ++i) {
          m_values[i] = 0;
        }
        return *this;
      }
    
      PUGS_INLINE
      constexpr TinyMatrix& operator=(IdentityType) noexcept
      {
        static_assert(std::is_arithmetic<T>(), "Cannot assign 'identity' value for non-arithmetic types");
        for (size_t i = 0; i < N; ++i) {
          for (size_t j = 0; j < N; ++j) {
            m_values[_index(i, j)] = (i == j) ? 1 : 0;
          }
        }
        return *this;
      }
    
      PUGS_INLINE
      constexpr TinyMatrix& operator=(const TinyMatrix& A) noexcept = default;
    
      PUGS_INLINE
      constexpr TinyMatrix& operator=(TinyMatrix&& A) noexcept = default;
    
      template <typename... Args>
      PUGS_INLINE constexpr TinyMatrix(const T& t, Args&&... args) noexcept
      {
        static_assert(sizeof...(args) == N * N - 1, "wrong number of parameters");
        this->_unpackVariadicInput(t, std::forward<Args>(args)...);
      }
    
      // One does not use the '=default' constructor to avoid (unexpected)
      // performances issues
      PUGS_INLINE
      constexpr TinyMatrix() noexcept {}
    
      PUGS_INLINE
      constexpr TinyMatrix(ZeroType) noexcept
      {
        static_assert(std::is_arithmetic<T>(), "Cannot construct from 'zero' value "
                                               "for non-arithmetic types");
        for (size_t i = 0; i < N * N; ++i) {
          m_values[i] = 0;
        }
      }
    
      PUGS_INLINE
      constexpr TinyMatrix(IdentityType) noexcept
      {
        static_assert(std::is_arithmetic<T>(), "Cannot construct from 'identity' "
                                               "value for non-arithmetic types");
        for (size_t i = 0; i < N; ++i) {
          for (size_t j = 0; j < N; ++j) {
            m_values[_index(i, j)] = (i == j) ? 1 : 0;
          }
        }
      }
    
      PUGS_INLINE
      constexpr TinyMatrix(const TinyMatrix&) noexcept = default;
    
      PUGS_INLINE
      TinyMatrix(TinyMatrix&& A) noexcept = default;
    
      PUGS_INLINE
      ~TinyMatrix() = default;
    };
    
    template <size_t N, typename T>
    PUGS_INLINE constexpr TinyMatrix<N, T>
    tensorProduct(const TinyVector<N, T>& x, const TinyVector<N, T>& y)
    {
      TinyMatrix<N, T> A;
      for (size_t i = 0; i < N; ++i) {
        for (size_t j = 0; j < N; ++j) {
          A(i, j) = x[i] * y[j];
        }
      }
      return A;
    }
    
    template <size_t N, typename T>
    PUGS_INLINE constexpr T
    det(const TinyMatrix<N, T>& A)
    {
      static_assert(std::is_arithmetic<T>::value, "determinent is not defined for non-arithmetic types");
      static_assert(std::is_floating_point<T>::value, "determinent for arbitrary dimension N is defined for floating "
                                                      "point types only");
      TinyMatrix<N, T> M = A;
    
      TinyVector<N, size_t> index;
      for (size_t i = 0; i < N; ++i)
        index[i] = i;
    
      T determinent = 1;
      for (size_t i = 0; i < N; ++i) {
        for (size_t j = i; j < N; ++j) {
          size_t l       = j;
          const size_t J = index[j];
          for (size_t k = j + 1; k < N; ++k) {
            if (std::abs(M(index[k], i)) > std::abs(M(J, i))) {
              l = k;
            }
          }
          if (l != j) {
            std::swap(index[l], index[j]);
            determinent *= -1;
          }
        }
        const size_t I = index[i];
        const T Mii    = M(I, i);
        if (Mii != 0) {
          const T inv_Mii = 1. / M(I, i);
          for (size_t k = i + 1; k < N; ++k) {
            const size_t K = index[k];
            const T factor = M(K, i) * inv_Mii;
            for (size_t l = i + 1; l < N; ++l) {
              M(K, l) -= factor * M(I, l);
            }
          }
        } else {
          return 0;
        }
      }
    
      for (size_t i = 0; i < N; ++i) {
        determinent *= M(index[i], i);
      }
      return determinent;
    }
    
    template <typename T>
    PUGS_INLINE constexpr T
    det(const TinyMatrix<1, T>& A)
    {
      static_assert(std::is_arithmetic<T>::value, "determinent is not defined for non-arithmetic types");
      return A(0, 0);
    }
    
    template <typename T>
    PUGS_INLINE constexpr T
    det(const TinyMatrix<2, T>& A)
    {
      static_assert(std::is_arithmetic<T>::value, "determinent is not defined for non-arithmetic types");
      return A(0, 0) * A(1, 1) - A(1, 0) * A(0, 1);
    }
    
    template <typename T>
    PUGS_INLINE constexpr T
    det(const TinyMatrix<3, T>& A)
    {
      static_assert(std::is_arithmetic<T>::value, "determinent is not defined for non-arithmetic types");
      return A(0, 0) * (A(1, 1) * A(2, 2) - A(2, 1) * A(1, 2)) - A(1, 0) * (A(0, 1) * A(2, 2) - A(2, 1) * A(0, 2)) +
             A(2, 0) * (A(0, 1) * A(1, 2) - A(1, 1) * A(0, 2));
    }
    
    template <size_t N, typename T>
    PUGS_INLINE constexpr TinyMatrix<N - 1, T>
    getMinor(const TinyMatrix<N, T>& A, size_t I, size_t J)
    {
      static_assert(N >= 2, "minor calculation requires at least 2x2 matrices");
      Assert((I < N) and (J < N));
      TinyMatrix<N - 1, T> M;
      for (size_t i = 0; i < I; ++i) {
        for (size_t j = 0; j < J; ++j) {
          M(i, j) = A(i, j);
        }
        for (size_t j = J + 1; j < N; ++j) {
          M(i, j - 1) = A(i, j);
        }
      }
      for (size_t i = I + 1; i < N; ++i) {
        for (size_t j = 0; j < J; ++j) {
          M(i - 1, j) = A(i, j);
        }
        for (size_t j = J + 1; j < N; ++j) {
          M(i - 1, j - 1) = A(i, j);
        }
      }
      return M;
    }
    
    template <size_t N, typename T>
    PUGS_INLINE constexpr TinyMatrix<N, T> inverse(const TinyMatrix<N, T>& A);
    
    template <typename T>
    PUGS_INLINE constexpr TinyMatrix<1, T>
    inverse(const TinyMatrix<1, T>& A)
    {
      static_assert(std::is_arithmetic<T>::value, "inverse is not defined for non-arithmetic types");
      static_assert(std::is_floating_point<T>::value, "inverse is defined for floating point types only");
    
      TinyMatrix<1, T> A_1(1. / A(0, 0));
      return A_1;
    }
    
    template <size_t N, typename T>
    PUGS_INLINE constexpr T
    cofactor(const TinyMatrix<N, T>& A, size_t i, size_t j)
    {
      static_assert(std::is_arithmetic<T>::value, "cofactor is not defined for non-arithmetic types");
      const T sign = ((i + j) % 2) ? -1 : 1;
    
      return sign * det(getMinor(A, i, j));
    }
    
    template <typename T>
    PUGS_INLINE constexpr TinyMatrix<2, T>
    inverse(const TinyMatrix<2, T>& A)
    {
      static_assert(std::is_arithmetic<T>::value, "inverse is not defined for non-arithmetic types");
      static_assert(std::is_floating_point<T>::value, "inverse is defined for floating point types only");
    
      const T determinent     = det(A);
      const T inv_determinent = 1. / determinent;
    
      TinyMatrix<2, T> A_cofactors_T(A(1, 1), -A(0, 1), -A(1, 0), A(0, 0));
      return A_cofactors_T *= inv_determinent;
    }
    
    template <typename T>
    PUGS_INLINE constexpr TinyMatrix<3, T>
    inverse(const TinyMatrix<3, T>& A)
    {
      static_assert(std::is_arithmetic<T>::value, "inverse is not defined for non-arithmetic types");
      static_assert(std::is_floating_point<T>::value, "inverse is defined for floating point types only");
    
      const T determinent = det(A);
    
      TinyMatrix<3, T> A_cofactors_T(cofactor(A, 0, 0), cofactor(A, 1, 0), cofactor(A, 2, 0), cofactor(A, 0, 1),
                                     cofactor(A, 1, 1), cofactor(A, 2, 1), cofactor(A, 0, 2), cofactor(A, 1, 2),
                                     cofactor(A, 2, 2));
    
      return A_cofactors_T *= 1. / determinent;
    }
    
    #endif   // TINYMATRIX_HPP