Page MenuHomec4science

static_types.hh
No OneTemporary

File Metadata

Created
Fri, May 17, 17:05

static_types.hh

/**
* @file
*
* @author Lucas Frérot <lucas.frerot@epfl.ch>
*
* @section LICENSE
*
* Copyright (©) 2017 EPFL (Ecole Polytechnique Fédérale de
* Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des
* Solides)
*
* Tamaas is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Tamaas is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Tamaas. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef __STATIC_TYPES_HH__
#define __STATIC_TYPES_HH__
/* -------------------------------------------------------------------------- */
#include "tamaas.hh"
__BEGIN_TAMAAS__
/* -------------------------------------------------------------------------- */
namespace detail {
template <UInt acc, UInt n, UInt... ns>
struct product_tail_rec {
static constexpr UInt value = product_tail_rec<acc * n, ns...>::value;
};
template <UInt acc, UInt n>
struct product_tail_rec<acc, n> {
static constexpr UInt value = acc * n;
};
template <UInt N, UInt n, UInt... ns>
struct get_rec {
static constexpr UInt value = get_rec<N-1, ns...>::value;
};
template <UInt n, UInt... ns>
struct get_rec<0, n, ns...> {
static constexpr UInt value = n;
};
}
template <UInt... ns>
struct product {
static constexpr UInt value = detail::product_tail_rec<1, ns...>::value;
};
template <UInt N, UInt... ns>
struct get {
static constexpr UInt value = detail::get_rec<N, ns...>::value;
};
template <typename T>
struct is_arithmetic : std::is_arithmetic<T> {};
template <typename T>
struct is_arithmetic<thrust::complex<T>> : std::true_type {};
/**
* @brief Static Array
*
* This class is meant to be a small and fast object for intermediate
* calculations, possibly on wrapped memory belonging to a grid. Support type
* show be either a pointer or a C array. It should not contain any virtual
* method.
*/
template <typename DataType, UInt size, typename SupportType = DataType*>
class StaticArray {
static_assert(std::is_array<SupportType>::value ||
std::is_pointer<SupportType>::value,
"the support type of StaticArray should be either a pointer or "
"a C-array");
using T = DataType;
public:
/// Access operator
__device__ __host__ T& operator()(UInt i) {
// TAMAAS_ASSERT(i < n, "Access out of bounds");
return _mem[i];
}
/// Access operator
__device__ __host__ const T& operator()(UInt i) const {
// TAMAAS_ASSERT(i < n, "Access out of bounds");
return _mem[i];
}
/// L2 norm squared
__device__ __host__ T l2squared() const {
T res = 0;
for (UInt i = 0; i < size; ++i)
res += _mem[i] * _mem[i];
return res;
}
/// L2 norm
__device__ __host__ T l2norm() const { return std::sqrt(l2squared()); }
#define VECTOR_OP(op) \
template <typename T1> \
__device__ __host__ void operator op(const StaticArray<T1, size>& o) { \
for (UInt i = 0; i < size; ++i) \
(*this)(i) op o(i); \
}
VECTOR_OP(+=)
VECTOR_OP(-=)
VECTOR_OP(*=)
VECTOR_OP(/=)
#undef VECTOR_OP
#define SCALAR_OP(op) \
template <typename T1> \
__device__ __host__ \
typename std::enable_if<is_arithmetic<T1>::value, StaticArray&>::type \
operator op(const T1& x) { \
for (UInt i = 0; i < size; ++i) \
(*this)(i) op x; \
return *this; \
}
SCALAR_OP(+=)
SCALAR_OP(-=)
SCALAR_OP(*=)
SCALAR_OP(/=)
SCALAR_OP(=)
#undef SCALAR_OP
/// Overriding the implit copy operator
StaticArray& operator=(const StaticArray& o) {
for (UInt i = 0; i < size; ++i)
(*this)(i) = o(i);
return *this;
}
protected:
SupportType _mem;
};
/**
* @brief Static Tensor
*
* This class implements a multi-dimensional tensor behavior.
*/
template <typename DataType, typename SupportType = DataType*, UInt... dims>
class StaticTensor
: public StaticArray<DataType, product<dims...>::value, SupportType> {
using parent = StaticArray<DataType, product<dims...>::value, SupportType>;
using T = DataType;
public:
static constexpr UInt dim = sizeof...(dims);
using parent::operator=;
private:
template <typename... Idx>
static UInt unpackOffset(UInt offset, UInt index, Idx... rest) {
constexpr UInt size = sizeof...(rest);
offset += index;
offset *= get<dim-size, dims...>::value;
return unpackOffset(offset, rest...);
}
template <typename... Idx>
static UInt unpackOffset(UInt offset, UInt index) {
return offset + index;
}
public:
template <typename... Idx>
const T& operator()(Idx... idx) const {
return this->_mem[unpackOffset(0, idx...)];
}
template <typename... Idx>
T& operator()(Idx... idx) {
return this->_mem[unpackOffset(0, idx...)];
}
};
/* -------------------------------------------------------------------------- */
/* Common Static Types */
/* -------------------------------------------------------------------------- */
/// Matrix class with size determined at compile time
template <typename T, UInt n, UInt m>
class StaticMatrix : public StaticTensor<T, T*, n, m> {
public:
/// Implicit wrap constructor
__device__ __host__ StaticMatrix(T& spot) {
this->_mem = &spot;
}
using StaticTensor<T, T*, n, m>::operator=;
};
/// Vector class with size determined at compile-time
template <typename T, UInt n>
class StaticVector : public StaticTensor<T, T*, n> {
public:
/// Implicit wrap constructor
__device__ __host__ StaticVector(T& spot) {
this->_mem = &spot;
}
using StaticTensor<T, T*, n>::operator=;
/// Matrix-vector product
template <typename T1, typename T2, UInt m>
__device__ __host__ void mul(const StaticMatrix<T1, n, m>& mat,
const StaticVector<T2, m>& vec) {
*this = T(0);
for (UInt i = 0; i < n; ++i)
for (UInt j = 0; j < m; ++j)
(*this)(i) += mat(i, j) * vec(j);
}
};
__END_TAMAAS__
#endif // __STATIC_TYPES_HH__

Event Timeline