#ifndef TINY_VECTOR_HPP #define TINY_VECTOR_HPP #include <iostream> #include <PastisAssert.hpp> #include <Kokkos_Core.hpp> #include <Types.hpp> template <size_t N, typename T=double> class TinyVector { private: T m_values[N]; static_assert((N>0),"TinyVector size must be strictly positive"); void _unpackVariadicInput(const T& t) { m_values[N-1] = t; } template <typename... Args> void _unpackVariadicInput(const T& t, Args&&... args) { m_values[N-1-sizeof...(args)] = t; this->_unpackVariadicInput(args...); } public: KOKKOS_INLINE_FUNCTION TinyVector operator-() const { TinyVector opposed; for (size_t i=0; i<N; ++i) { opposed.m_values[i] =-m_values[i]; } return std::move(opposed); } KOKKOS_INLINE_FUNCTION constexpr size_t dimension() const { return N; } KOKKOS_INLINE_FUNCTION bool operator==(const TinyVector& v) const { for (size_t i=0; i<N; ++i) { if (m_values[i] != v.m_values[i]) return false; } return true; } KOKKOS_INLINE_FUNCTION bool operator!=(const TinyVector& v) const { return not this->operator==(v); } KOKKOS_INLINE_FUNCTION T operator,(const TinyVector& v) const { T t = m_values[0]*v.m_values[0]; for (size_t i=1; i<N; ++i) { t += m_values[i]*v.m_values[i]; } return std::move(t); } KOKKOS_INLINE_FUNCTION TinyVector& operator*=(const T& t) { for (size_t i=0; i<N; ++i) { m_values[i] *= t; } return *this; } KOKKOS_INLINE_FUNCTION friend TinyVector operator*(const T& t, const TinyVector& v) { TinyVector tv; for (size_t i=0; i<N; ++i) { tv.m_values[i] = t * v.m_values[i]; } return std::move(tv); } KOKKOS_INLINE_FUNCTION friend TinyVector operator*(const T& t, TinyVector&& v) { v *= t; return std::move(v); } KOKKOS_INLINE_FUNCTION friend std::ostream& operator<<(std::ostream& os, const TinyVector& v) { os << '(' << v.m_values[0]; for (size_t i=1; i<N; ++i) { os << ',' << v.m_values[i]; } os << ')'; return os; } KOKKOS_INLINE_FUNCTION TinyVector operator+(const TinyVector& v) const { TinyVector sum; for (size_t i=0; i<N; ++i) { sum.m_values[i] = m_values[i]+v.m_values[i]; } return std::move(sum); } KOKKOS_INLINE_FUNCTION TinyVector operator+(TinyVector&& v) const { for (size_t i=0; i<N; ++i) { v.m_values[i] += m_values[i]; } return std::move(v); } KOKKOS_INLINE_FUNCTION TinyVector operator-(const TinyVector& v) const { TinyVector difference; for (size_t i=0; i<N; ++i) { difference.m_values[i] = m_values[i]-v.m_values[i]; } return std::move(difference); } KOKKOS_INLINE_FUNCTION TinyVector operator-(TinyVector&& v) const { for (size_t i=0; i<N; ++i) { v.m_values[i] = m_values[i]-v.m_values[i]; } return std::move(v); } KOKKOS_INLINE_FUNCTION TinyVector& operator+=(const TinyVector& v) { for (size_t i=0; i<N; ++i) { m_values[i] += v.m_values[i]; } return *this; } KOKKOS_INLINE_FUNCTION TinyVector& operator-=(const TinyVector& v) { for (size_t i=0; i<N; ++i) { m_values[i] -= v.m_values[i]; } return *this; } KOKKOS_INLINE_FUNCTION T& operator[](const size_t& i) { Assert(i<N); return m_values[i]; } KOKKOS_INLINE_FUNCTION const T& operator[](const size_t& i) const { Assert(i<N); return m_values[i]; } KOKKOS_INLINE_FUNCTION TinyVector& operator=(const ZeroType& z) { static_assert(std::is_arithmetic<T>(),"Cannot assign 'zero' value for non-arithmetic types"); for (size_t i=0; i<N; ++i) { m_values[i] = 0; } return *this; } KOKKOS_INLINE_FUNCTION const TinyVector& operator=(const TinyVector& v) { for (size_t i=0; i<N; ++i) { m_values[i] = v.m_values[i]; } return *this; } KOKKOS_INLINE_FUNCTION TinyVector& operator=(TinyVector&& v) = default; template <typename... Args> KOKKOS_INLINE_FUNCTION TinyVector(const T& t, Args&&... args) { static_assert(sizeof...(args)==N-1, "wrong number of parameters"); this->_unpackVariadicInput(t, args...); } KOKKOS_INLINE_FUNCTION TinyVector() { ; } KOKKOS_INLINE_FUNCTION TinyVector(const ZeroType& z) { static_assert(std::is_arithmetic<T>(),"Cannot construct from 'zero' value for non-arithmetic types"); for (size_t i=0; i<N; ++i) { m_values[i] = 0; } } KOKKOS_INLINE_FUNCTION TinyVector(const TinyVector& v) { for (size_t i=0; i<N; ++i) { m_values[i] = v.m_values[i]; } } KOKKOS_INLINE_FUNCTION TinyVector(TinyVector&& v) = default; KOKKOS_INLINE_FUNCTION ~TinyVector() { ; } }; template <size_t N, typename T> KOKKOS_INLINE_FUNCTION T l2Norm(const TinyVector<N,T>& x) { static_assert(std::is_arithmetic<T>(),"Cannot compute L2 norm for non-arithmetic types"); return std::sqrt((x,x)); } #endif // TINYVECTOR_HPP