Files
cpp-thirdparty/noarch/include/Fastor/tensor/Tensor.h
2025-03-22 01:17:52 -05:00

204 lines
8.6 KiB
C++

#ifndef TENSOR_H
#define TENSOR_H
#include "Fastor/config/config.h"
#include "Fastor/util/util.h"
#include "Fastor/backend/backend.h"
#include "Fastor/simd_vector/SIMDVector.h"
#include "Fastor/tensor/AbstractTensor.h"
#include "Fastor/tensor/Ranges.h"
#include "Fastor/tensor/ForwardDeclare.h"
#include "Fastor/expressions/linalg_ops/linalg_ops.h"
#include <array>
#include <vector>
namespace Fastor {
template<typename T, size_t ... Rest>
class Tensor: public AbstractTensor<Tensor<T,Rest...>,sizeof...(Rest)> {
public:
using scalar_type = T;
using simd_vector_type = choose_best_simd_vector_t<T>;
using simd_abi_type = typename simd_vector_type::abi_type;
using result_type = Tensor<T,Rest...>;
using dimension_t = std::integral_constant<FASTOR_INDEX, sizeof...(Rest)>;
static constexpr FASTOR_INLINE FASTOR_INDEX rank() {return sizeof...(Rest);}
static constexpr FASTOR_INLINE FASTOR_INDEX size() {return pack_prod<Rest...>::value;}
FASTOR_INLINE FASTOR_INDEX dimension(FASTOR_INDEX dim) const {
#if FASTOR_SHAPE_CHECK
FASTOR_ASSERT(dim>=0 && dim < sizeof...(Rest), "TENSOR SHAPE MISMATCH");
#endif
constexpr FASTOR_INDEX DimensionHolder[sizeof...(Rest)] = {Rest...};
return DimensionHolder[dim];
}
FASTOR_INLINE Tensor<T,Rest...>& noalias() {return *this;}
// Classic constructors
//----------------------------------------------------------------------------------------------------------//
// Default constructor
constexpr FASTOR_INLINE Tensor() = default;
// Copy constructor
FASTOR_INLINE Tensor(const Tensor<T,Rest...> &other) {
// This constructor cannot be default
if (_data == other.data()) return;
// fast memcopy
std::copy(other.data(),other.data()+size(),_data);
};
// Constructor from a scalar
template<typename U=T, enable_if_t_<is_primitive_v_<U>,bool> = false>
constexpr FASTOR_INLINE Tensor(U num) {
#ifdef FASTOR_ZERO_INITIALISE
// This is for compile time initialisation, so it is fine
scalar_type cnum = (scalar_type)num;
FASTOR_INDEX i = 0;
for (; i<size(); ++i) {
_data[i] = cnum;
}
#else
assign(*this, num);
#endif
}
// Initialiser list constructors
//----------------------------------------------------------------------------------------------------------//
#include "Fastor/tensor/InitializerListConstructors.h"
//----------------------------------------------------------------------------------------------------------//
// Classic array wrappers
//----------------------------------------------------------------------------------------------------------//
FASTOR_INLINE Tensor(const T *arr, int layout=RowMajor) {
std::copy(arr,arr+size(),_data);
if (layout == RowMajor)
return;
else
*this = tocolumnmajor(*this);
}
FASTOR_INLINE Tensor(const std::array<T,pack_prod<Rest...>::value> &arr, int layout=RowMajor) {
std::copy(arr.data(),arr.data()+pack_prod<Rest...>::value,_data);
if (layout == RowMajor)
return;
else
*this = tocolumnmajor(*this);
}
FASTOR_INLINE Tensor(const std::vector<T> &arr, int layout=RowMajor) {
std::copy(arr.data(),arr.data()+pack_prod<Rest...>::value,_data);
if (layout == RowMajor)
return;
else
*this = tocolumnmajor(*this);
}
//----------------------------------------------------------------------------------------------------------//
// CRTP constructors
//----------------------------------------------------------------------------------------------------------//
//----------------------------------------------------------------------------------------------------------//
// Generic AbstractTensors
#ifndef FASTOR_DISABLE_SPECIALISED_CTR
template<typename Derived, size_t DIMS,
enable_if_t_<(!has_tensor_view_v<Derived> && !has_tensor_fixed_view_2d_v<Derived> &&
!has_tensor_fixed_view_nd_v<Derived>) || DIMS!=sizeof...(Rest),bool> = false>
#else
template<typename Derived, size_t DIMS>
#endif
FASTOR_INLINE Tensor(const AbstractTensor<Derived,DIMS>& src) {
FASTOR_ASSERT(src.self().size()==size(), "TENSOR SIZE MISMATCH");
assign(*this, src.self());
}
//----------------------------------------------------------------------------------------------------------//
// Specialised constructors
//----------------------------------------------------------------------------------------------------------//
#include "Fastor/tensor/SpecialisedConstructors.h"
//----------------------------------------------------------------------------------------------------------//
// AbstractTensor and scalar in-place operators
//----------------------------------------------------------------------------------------------------------//
#include "Fastor/tensor/TensorInplaceOperators.h"
//----------------------------------------------------------------------------------------------------------//
// Raw pointer providers
//----------------------------------------------------------------------------------------------------------//
#ifdef FASTOR_ZERO_INITIALISE
constexpr FASTOR_INLINE T* data() const { return const_cast<T*>(this->_data);}
#else
FASTOR_INLINE T* data() const { return const_cast<T*>(this->_data);}
#endif
FASTOR_INLINE T* data() {return this->_data;}
//----------------------------------------------------------------------------------------------------------//
// Scalar & block indexing
//----------------------------------------------------------------------------------------------------------//
#include "Fastor/tensor/IndexRetriever.h"
#include "Fastor/tensor/ScalarIndexing.h"
#include "Fastor/tensor/BlockIndexing.h"
//----------------------------------------------------------------------------------------------------------//
// Expression templates evaluators
//----------------------------------------------------------------------------------------------------------//
#include "Fastor/tensor/TensorEvaluator.h"
//----------------------------------------------------------------------------------------------------------//
// Tensor methods
//----------------------------------------------------------------------------------------------------------//
#include "Fastor/tensor/TensorMethods.h"
//----------------------------------------------------------------------------------------------------------//
// Converters
//----------------------------------------------------------------------------------------------------------//
#include "Fastor/tensor/PODConverters.h"
//----------------------------------------------------------------------------------------------------------//
// Cast method
//----------------------------------------------------------------------------------------------------------//
template<typename U>
FASTOR_INLINE Tensor<U,Rest...> cast() const {
Tensor<U,Rest...> out;
U *out_data = out.data();
for (FASTOR_INDEX i=0; i<size(); ++i) {
out_data[get_mem_index(i)] = static_cast<U>(_data[i]);
}
return out;
}
//----------------------------------------------------------------------------------------------------------//
//----------------------------------------------------------------------------------------------------------//
protected:
template<typename Derived, size_t DIMS>
FASTOR_INLINE void verify_dimensions(const AbstractTensor<Derived,DIMS>& src_) const {
static_assert(DIMS==dimension_t::value, "TENSOR RANK MISMATCH");
#ifndef NDEBUG
const Derived &src = src_.self();
FASTOR_ASSERT(src.size()==this->size(), "TENSOR SIZE MISMATCH");
// Check if shape of tensors match
for (FASTOR_INDEX i=0; i<dimension_t::value; ++i) {
FASTOR_ASSERT(src.dimension(i)==dimension(i), "TENSOR SHAPE MISMATCH");
}
#endif
}
//----------------------------------------------------------------------------------------------------------//
//----------------------------------------------------------------------------------------------------------//
private:
#ifdef FASTOR_ZERO_INITIALISE
FASTOR_ALIGN T _data[pack_prod<Rest...>::value] = {};
#else
FASTOR_ALIGN T _data[pack_prod<Rest...>::value];
#endif
//----------------------------------------------------------------------------------------------------------//
};
} // end of namespace Fastor
#include "Fastor/tensor/TensorAssignment.h"
#endif // TENSOR_H