Add Fastor library

This commit is contained in:
Bassem Girgis
2025-03-22 01:17:52 -05:00
parent 5546e086f6
commit 4dd5939693
132 changed files with 55086 additions and 0 deletions

View File

@@ -0,0 +1,317 @@
#ifndef TENSOR_DIAG_VIEWS_H
#define TENSOR_DIAG_VIEWS_H
#include "Fastor/tensor/Tensor.h"
#include "Fastor/tensor/TensorMap.h"
#include "Fastor/tensor/Ranges.h"
#include "Fastor/expressions/linalg_ops/linalg_traits.h"
namespace Fastor {
template<template<typename,size_t...> class TensorType, typename T, size_t M, size_t N, size_t DIM>
struct TensorDiagViewExpr<TensorType<T,M,N>,DIM> : public AbstractTensor<TensorDiagViewExpr<TensorType<T,M,N>,DIM>,DIM> {
private:
TensorType<T,M,N>& _expr;
bool _does_alias = false;
constexpr FASTOR_INLINE Tensor<T,M,N> get_tensor() const {return _expr;};
public:
using scalar_type = T;
using simd_vector_type = typename Tensor<T,M,N>::simd_vector_type;
using simd_abi_type = typename simd_vector_type::abi_type;
using result_type = Tensor<T,M>;
using V = SIMDVector<T,simd_abi_type>;
static constexpr FASTOR_INDEX Dimension = 1;
static constexpr FASTOR_INDEX Stride = simd_vector_type::Size;
static constexpr FASTOR_INDEX rank() {return 1;}
constexpr FASTOR_INLINE FASTOR_INDEX size() const {return M;}
constexpr FASTOR_INLINE FASTOR_INDEX dimension(FASTOR_INDEX ) const {return M;}
constexpr const TensorType<T,M,N>& expr() const {return _expr;}
FASTOR_INLINE TensorViewExpr<TensorType<T,M,N>,2>& noalias() {
_does_alias = true;
return *this;
}
FASTOR_INLINE TensorDiagViewExpr(Tensor<T,M,N> &_ex) : _expr(_ex) {
static_assert(M==N, "MATRIX MUST BE SQUARE FOR DIAGONAL VIEW");
}
// Copy assignment
//---------------------------------------------------------------------------------//
FASTOR_INLINE void operator=(const TensorDiagViewExpr<TensorType<T,M,N>,DIM>& other_src) {
// Diagonal views don't alias
#if !(FASTOR_NO_ALIAS)
if (_does_alias) {
// Get around recursive inlining issue
const result_type tmp(other_src);
this->operator=(tmp);
return;
}
#endif
#ifndef NDEBUG
FASTOR_ASSERT(other_src.size()==this->size(), "TENSOR SIZE MISMATCH");
// Check if shape of tensors match
for (FASTOR_INDEX i=0; i<Dimension; ++i) {
FASTOR_ASSERT(other_src.dimension(i)==dimension(i), "TENSOR SHAPE MISMATCH");
}
#endif
for (FASTOR_INDEX i = 0; i < M; ++i) {
_expr(i,i) = other_src.template eval_s<T>(i,i);
}
}
// AbstractTensor binders
//---------------------------------------------------------------------------------//
template<typename Derived, size_t DIMS, enable_if_t_<requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator=(const AbstractTensor<Derived,DIMS> &other) {
const typename Derived::result_type& tmp = evaluate(other.self());
this->operator=(tmp);
}
template<typename Derived, size_t DIMS, enable_if_t_<!requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator=(const AbstractTensor<Derived,DIMS> &other) {
#if !(FASTOR_NO_ALIAS)
if (_does_alias) {
_does_alias = false;
// Evaluate this into a temporary
auto tmp_this_tensor = get_tensor();
auto tmp = TensorDiagViewExpr<TensorType<T,M,N>,2>(tmp_this_tensor);
// Assign other to temporary
tmp = other;
// assign temporary to this
this->operator=(tmp);
return;
}
#endif
const Derived& other_src = other.self();
#ifndef NDEBUG
FASTOR_ASSERT(other_src.size()==this->size(), "TENSOR SIZE MISMATCH");
#endif
for (FASTOR_INDEX i = 0; i < M; ++i) {
_expr(i,i) = other_src.template eval_s<T>(i);
}
}
template<typename Derived, size_t DIMS, enable_if_t_<requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator+=(const AbstractTensor<Derived,DIMS> &other) {
const typename Derived::result_type& tmp = evaluate(other.self());
this->operator+=(tmp);
}
template<typename Derived, size_t DIMS, enable_if_t_<!requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator+=(const AbstractTensor<Derived,DIMS> &other) {
#if !(FASTOR_NO_ALIAS)
if (_does_alias) {
_does_alias = false;
// Evaluate this into a temporary
auto tmp_this_tensor = get_tensor();
auto tmp = TensorDiagViewExpr<TensorType<T,M,N>,2>(tmp_this_tensor);
// Assign other to temporary
tmp = other;
// assign temporary to this
this->operator+=(tmp);
return;
}
#endif
const Derived& other_src = other.self();
#ifndef NDEBUG
FASTOR_ASSERT(other_src.size()==this->size(), "TENSOR SIZE MISMATCH");
#endif
for (FASTOR_INDEX i = 0; i < M; ++i) {
_expr(i,i) += other_src.template eval_s<T>(i);
}
}
template<typename Derived, size_t DIMS, enable_if_t_<requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator-=(const AbstractTensor<Derived,DIMS> &other) {
const typename Derived::result_type& tmp = evaluate(other.self());
this->operator-=(tmp);
}
template<typename Derived, size_t DIMS, enable_if_t_<!requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator-=(const AbstractTensor<Derived,DIMS> &other) {
#if !(FASTOR_NO_ALIAS)
if (_does_alias) {
_does_alias = false;
// Evaluate this into a temporary
auto tmp_this_tensor = get_tensor();
auto tmp = TensorDiagViewExpr<TensorType<T,M,N>,2>(tmp_this_tensor);
// Assign other to temporary
tmp = other;
// assign temporary to this
this->operator-=(tmp);
return;
}
#endif
const Derived& other_src = other.self();
#ifndef NDEBUG
FASTOR_ASSERT(other_src.size()==this->size(), "TENSOR SIZE MISMATCH");
#endif
for (FASTOR_INDEX i = 0; i < M; ++i) {
_expr(i,i) -= other_src.template eval_s<T>(i);
}
}
template<typename Derived, size_t DIMS, enable_if_t_<requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator*=(const AbstractTensor<Derived,DIMS> &other) {
const typename Derived::result_type& tmp = evaluate(other.self());
this->operator*=(tmp);
}
template<typename Derived, size_t DIMS, enable_if_t_<!requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator*=(const AbstractTensor<Derived,DIMS> &other) {
#if !(FASTOR_NO_ALIAS)
if (_does_alias) {
_does_alias = false;
// Evaluate this into a temporary
auto tmp_this_tensor = get_tensor();
auto tmp = TensorDiagViewExpr<TensorType<T,M,N>,2>(tmp_this_tensor);
// Assign other to temporary
tmp = other;
// assign temporary to this
this->operator*=(tmp);
return;
}
#endif
const Derived& other_src = other.self();
#ifndef NDEBUG
FASTOR_ASSERT(other_src.size()==this->size(), "TENSOR SIZE MISMATCH");
#endif
for (FASTOR_INDEX i = 0; i < M; ++i) {
_expr(i,i) *= other_src.template eval_s<T>(i);
}
}
template<typename Derived, size_t DIMS, enable_if_t_<requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator/=(const AbstractTensor<Derived,DIMS> &other) {
const typename Derived::result_type& tmp = evaluate(other.self());
this->operator/=(tmp);
}
template<typename Derived, size_t DIMS, enable_if_t_<!requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator/=(const AbstractTensor<Derived,DIMS> &other) {
#if !(FASTOR_NO_ALIAS)
if (_does_alias) {
_does_alias = false;
// Evaluate this into a temporary
auto tmp_this_tensor = get_tensor();
auto tmp = TensorDiagViewExpr<TensorType<T,M,N>,2>(tmp_this_tensor);
// Assign other to temporary
tmp = other;
// assign temporary to this
this->operator/=(tmp);
return;
}
#endif
const Derived& other_src = other.self();
#ifndef NDEBUG
FASTOR_ASSERT(other_src.size()==this->size(), "TENSOR SIZE MISMATCH");
#endif
for (FASTOR_INDEX i = 0; i < M; ++i) {
_expr(i,i) /= other_src.template eval_s<T>(i);
}
}
// Scalar binders
//---------------------------------------------------------------------------------//
template<typename U, enable_if_t_<is_arithmetic_v_<U>,bool> = false>
FASTOR_HINT_INLINE void operator=(U num) {
for (FASTOR_INDEX i = 0; i < M; ++i) {
_expr(i,i) = num;
}
}
template<typename U, enable_if_t_<is_arithmetic_v_<U>,bool> = false>
FASTOR_HINT_INLINE void operator+=(U num) {
for (FASTOR_INDEX i = 0; i < M; ++i) {
_expr(i,i) += num;
}
}
template<typename U, enable_if_t_<is_arithmetic_v_<U>,bool> = false>
FASTOR_HINT_INLINE void operator-=(U num) {
for (FASTOR_INDEX i = 0; i < M; ++i) {
_expr(i,i) -= num;
}
}
template<typename U, enable_if_t_<is_arithmetic_v_<U>,bool> = false>
FASTOR_HINT_INLINE void operator*=(U num) {
for (FASTOR_INDEX i = 0; i < M; ++i) {
_expr(i,i) *= num;
}
}
template<typename U, enable_if_t_<is_arithmetic_v_<U> && !is_integral_v_<U>,bool> = false>
FASTOR_HINT_INLINE void operator/=(U num) {
T inum = T(1) / T(num);
for (FASTOR_INDEX i = 0; i < M; ++i) {
_expr(i,i) *= inum;
}
}
template<typename U, enable_if_t_<is_arithmetic_v_<U> && is_integral_v_<U>,bool> = false>
FASTOR_HINT_INLINE void operator/=(U num) {
for (FASTOR_INDEX i = 0; i < M; ++i) {
_expr(i,i) /= num;
}
}
// Evaluators
//---------------------------------------------------------------------------------//
template<typename U=T>
FASTOR_INLINE SIMDVector<U,simd_abi_type> eval(FASTOR_INDEX idx) const {
V _vec;
std::array<int,V::Size> inds;
for (auto j=0; j<V::Size; ++j) {
const size_t it = idx+j;
inds[j] = it*N+it;
}
vector_setter(_vec,_expr.data(),inds);
return _vec;
}
template<typename U=T>
FASTOR_INLINE U eval_s(FASTOR_INDEX idx) const {
return _expr(idx,idx);
}
template<typename U=T>
FASTOR_INLINE SIMDVector<U,simd_abi_type> eval(FASTOR_INDEX i, FASTOR_INDEX j) const {
V _vec;
vector_setter(_vec,_expr.data(),i*N+j);
return _vec;
}
template<typename U=T>
constexpr FASTOR_INLINE U eval_s(FASTOR_INDEX i, FASTOR_INDEX j) const {
return _expr(i,j);
}
template<typename U=T>
FASTOR_INLINE SIMDVector<U,simd_abi_type> teval(const std::array<int,2>& as) const {
V _vec;
vector_setter(_vec,_expr.data(),as[0]*N+as[1]);
return _vec;
}
template<typename U=T>
constexpr FASTOR_INLINE U teval_s(const std::array<int,2>& as) const {
return _expr.eval_s(as);
}
};
// Actual definition of diag function
// Note that like other views the input can only be an evaluated tensor
template<typename T, size_t M, size_t N>
TensorDiagViewExpr<Tensor<T,M,N>,2> diag(Tensor<T,M,N> &a) {
return TensorDiagViewExpr<Tensor<T,M,N>,2>(a);
}
template<typename T, size_t M, size_t N>
TensorDiagViewExpr<TensorMap<T,M,N>,2> diag(TensorMap<T,M,N> &a) {
return TensorDiagViewExpr<TensorMap<T,M,N>,2>(a);
}
} // end of namespace Fastor
#endif

View File

@@ -0,0 +1,281 @@
#ifndef TENSOR_FILTER_VIEWS_H
#define TENSOR_FILTER_VIEWS_H
#include "Fastor/tensor/Tensor.h"
#include "Fastor/expressions/linalg_ops/linalg_traits.h"
namespace Fastor {
template<typename T, size_t ... Rest, size_t DIMS>
struct TensorFilterViewExpr<Tensor<T,Rest...>,Tensor<bool,Rest...>,DIMS>:
public AbstractTensor<TensorFilterViewExpr<Tensor<T,Rest...>,Tensor<bool,Rest...>,DIMS>,DIMS> {
private:
Tensor<T,Rest...> &_expr;
const Tensor<bool,Rest...> &fl_expr;
bool _does_alias = false;
constexpr FASTOR_INLINE Tensor<T,Rest...> get_tensor() const {return _expr;}
public:
using scalar_type = T;
using simd_vector_type = typename Tensor<T,Rest...>::simd_vector_type;
using simd_abi_type = typename simd_vector_type::abi_type;
using result_type = Tensor<T,Rest...>;
static constexpr FASTOR_INDEX Dimension = DIMS;
static constexpr FASTOR_INDEX Stride = simd_vector_type::Size;
static constexpr FASTOR_INDEX rank() {return DIMS;}
constexpr FASTOR_INLINE FASTOR_INDEX size() const {return pack_prod<Rest...>::value;}
constexpr FASTOR_INLINE FASTOR_INDEX dimension(FASTOR_INDEX i) const {return fl_expr.dimension(i);}
constexpr const Tensor<T,Rest...>& expr() const {return _expr;}
FASTOR_INLINE TensorFilterViewExpr<Tensor<T,Rest...>,Tensor<bool,Rest...>,DIMS>& noalias() {
_does_alias = true;
return *this;
}
constexpr FASTOR_INLINE TensorFilterViewExpr(Tensor<T,Rest...> &_ex, const Tensor<bool,Rest...> &_it) : _expr(_ex), fl_expr(_it) {
static_assert(sizeof...(Rest)==DIMS, "INDEXING TENSOR WITH INCORRECT NUMBER OF ARGUMENTS");
}
// In place operators
//------------------------------------------------------------------------------------//
void operator=(const TensorFilterViewExpr<Tensor<T,Rest...>,Tensor<bool,Rest...>,DIMS> &src) {
#ifndef NDEBUG
FASTOR_ASSERT(src.size()==this->size(), "TENSOR SIZE MISMATCH");
// Check if shape of tensors match
for (FASTOR_INDEX i=0; i<Dimension; ++i) {
FASTOR_ASSERT(src.dimension(i)==dimension(i), "TENSOR SHAPE MISMATCH");
}
#endif
for (FASTOR_INDEX i = 0; i <size(); i++) {
if (fl_expr.eval_s(i)) {
_expr.data()[i] = src.template eval_s<T>(i);
}
}
}
template<typename Derived, size_t OTHER_DIMS, enable_if_t_<requires_evaluation_v<Derived>,bool> = false>
void operator=(const AbstractTensor<Derived,OTHER_DIMS> &src) {
const typename Derived::result_type& tmp = evaluate(src.self());
this->operator=(tmp);
}
template<typename Derived, size_t OTHER_DIMS, enable_if_t_<!requires_evaluation_v<Derived>,bool> = false>
void operator=(const AbstractTensor<Derived,OTHER_DIMS> &src) {
#ifndef NDEBUG
FASTOR_ASSERT(src.self().size()==this->size(), "TENSOR SIZE MISMATCH");
// Check if shape of tensors match
for (FASTOR_INDEX i=0; i<Dimension; ++i) {
FASTOR_ASSERT(src.self().dimension(i)==dimension(i), "TENSOR SHAPE MISMATCH");
}
#endif
for (FASTOR_INDEX i = 0; i <size(); i++) {
if (fl_expr.eval_s(i)) {
_expr.data()[i] = src.self().template eval_s<T>(i);
}
}
}
template<typename Derived, size_t OTHER_DIMS, enable_if_t_<requires_evaluation_v<Derived>,bool> = false>
void operator+=(const AbstractTensor<Derived,OTHER_DIMS> &src) {
const typename Derived::result_type& tmp = evaluate(src.self());
this->operator+=(tmp);
}
template<typename Derived, size_t OTHER_DIMS, enable_if_t_<!requires_evaluation_v<Derived>,bool> = false>
void operator+=(const AbstractTensor<Derived,OTHER_DIMS> &src) {
#ifndef NDEBUG
FASTOR_ASSERT(src.self().size()==this->size(), "TENSOR SIZE MISMATCH");
// Check if shape of tensors match
for (FASTOR_INDEX i=0; i<Dimension; ++i) {
FASTOR_ASSERT(src.self().dimension(i)==dimension(i), "TENSOR SHAPE MISMATCH");
}
#endif
for (FASTOR_INDEX i = 0; i <size(); i++) {
if (fl_expr.eval_s(i)) {
_expr.data()[i] += src.self().template eval_s<T>(i);
}
}
}
template<typename Derived, size_t OTHER_DIMS, enable_if_t_<requires_evaluation_v<Derived>,bool> = false>
void operator-=(const AbstractTensor<Derived,OTHER_DIMS> &src) {
const typename Derived::result_type& tmp = evaluate(src.self());
this->operator-=(tmp);
}
template<typename Derived, size_t OTHER_DIMS, enable_if_t_<!requires_evaluation_v<Derived>,bool> = false>
void operator-=(const AbstractTensor<Derived,OTHER_DIMS> &src) {
#ifndef NDEBUG
FASTOR_ASSERT(src.self().size()==this->size(), "TENSOR SIZE MISMATCH");
// Check if shape of tensors match
for (FASTOR_INDEX i=0; i<Dimension; ++i) {
FASTOR_ASSERT(src.self().dimension(i)==dimension(i), "TENSOR SHAPE MISMATCH");
}
#endif
for (FASTOR_INDEX i = 0; i <size(); i++) {
if (fl_expr.eval_s(i)) {
_expr.data()[i] -= src.self().template eval_s<T>(i);
}
}
}
template<typename Derived, size_t OTHER_DIMS, enable_if_t_<requires_evaluation_v<Derived>,bool> = false>
void operator*=(const AbstractTensor<Derived,OTHER_DIMS> &src) {
const typename Derived::result_type& tmp = evaluate(src.self());
this->operator*=(tmp);
}
template<typename Derived, size_t OTHER_DIMS, enable_if_t_<!requires_evaluation_v<Derived>,bool> = false>
void operator*=(const AbstractTensor<Derived,OTHER_DIMS> &src) {
#ifndef NDEBUG
FASTOR_ASSERT(src.self().size()==this->size(), "TENSOR SIZE MISMATCH");
// Check if shape of tensors match
for (FASTOR_INDEX i=0; i<Dimension; ++i) {
FASTOR_ASSERT(src.self().dimension(i)==dimension(i), "TENSOR SHAPE MISMATCH");
}
#endif
for (FASTOR_INDEX i = 0; i <size(); i++) {
if (fl_expr.eval_s(i)) {
_expr.data()[i] *= src.self().template eval_s<T>(i);
}
}
}
template<typename Derived, size_t OTHER_DIMS, enable_if_t_<requires_evaluation_v<Derived>,bool> = false>
void operator/=(const AbstractTensor<Derived,OTHER_DIMS> &src) {
const typename Derived::result_type& tmp = evaluate(src.self());
this->operator/=(tmp);
}
template<typename Derived, size_t OTHER_DIMS, enable_if_t_<!requires_evaluation_v<Derived>,bool> = false>
void operator/=(const AbstractTensor<Derived,OTHER_DIMS> &src) {
#ifndef NDEBUG
FASTOR_ASSERT(src.self().size()==this->size(), "TENSOR SIZE MISMATCH");
// Check if shape of tensors match
for (FASTOR_INDEX i=0; i<Dimension; ++i) {
FASTOR_ASSERT(src.self().dimension(i)==dimension(i), "TENSOR SHAPE MISMATCH");
}
#endif
for (FASTOR_INDEX i = 0; i <size(); i++) {
if (fl_expr.eval_s(i)) {
_expr.data()[i] /= src.self().template eval_s<T>(i);
}
}
}
//------------------------------------------------------------------------------------//
template<typename U=T, enable_if_t_<is_arithmetic_v_<U>,bool> = false>
void operator=(U num) {
T tnum = (T)num;
for (FASTOR_INDEX i = 0; i <size(); i++) {
if (fl_expr.eval_s(i)) {
_expr.data()[i] = tnum;
}
}
}
template<typename U=T, enable_if_t_<is_arithmetic_v_<U>,bool> = false>
void operator+=(U num) {
T tnum = (T)num;
for (FASTOR_INDEX i = 0; i <size(); i++) {
if (fl_expr.eval_s(i)) {
_expr.data()[i] += tnum;
}
}
}
template<typename U=T, enable_if_t_<is_arithmetic_v_<U>,bool> = false>
void operator-=(U num) {
T tnum = (T)num;
for (FASTOR_INDEX i = 0; i <size(); i++) {
if (fl_expr.eval_s(i)) {
_expr.data()[i] -= tnum;
}
}
}
template<typename U=T, enable_if_t_<is_arithmetic_v_<U>,bool> = false>
void operator*=(U num) {
T tnum = (T)num;
for (FASTOR_INDEX i = 0; i <size(); i++) {
if (fl_expr.eval_s(i)) {
_expr.data()[i] *= tnum;
}
}
}
template<typename U=T, enable_if_t_<is_arithmetic_v_<U> && !is_integral_v_<U>,bool> = false>
void operator/=(U num) {
T tnum = T(1)/(T)num;
for (FASTOR_INDEX i = 0; i <size(); i++) {
if (fl_expr.eval_s(i)) {
_expr.data()[i] *= tnum;
}
}
}
template<typename U=T, enable_if_t_<is_arithmetic_v_<U> && is_integral_v_<U>,bool> = false>
void operator/=(U num) {
T tnum = (T)num;
for (FASTOR_INDEX i = 0; i <size(); i++) {
if (fl_expr.eval_s(i)) {
_expr.data()[i] /= tnum;
}
}
}
//------------------------------------------------------------------------------------//
//------------------------------------------------------------------------------------//
template<typename U=T>
FASTOR_INLINE SIMDVector<U,simd_abi_type> eval(FASTOR_INDEX i) const {
constexpr size_t _Stride = SIMDVector<T,simd_abi_type>::Size;
SIMDVector<U,simd_abi_type> _vec;
U inds[_Stride];
for (FASTOR_INDEX j=0; j<_Stride; ++j)
inds[j] = fl_expr.eval_s(i+j) ? _expr.eval_s(i+j) : 0;
_vec.load(inds,false);
return _vec;
}
template<typename U=T>
FASTOR_INLINE U eval_s(FASTOR_INDEX i) const {
return fl_expr.eval_s(i) ? _expr.eval_s(i) : 0;
}
template<typename U=T>
FASTOR_INLINE SIMDVector<U,simd_abi_type> eval(FASTOR_INDEX i, FASTOR_INDEX k) const {
constexpr size_t _Stride = SIMDVector<T,simd_abi_type>::Size;
SIMDVector<U,simd_abi_type> _vec;
U inds[_Stride];
for (FASTOR_INDEX j=0; j<_Stride; ++j)
inds[j] = fl_expr.eval_s(i,k+j) ? _expr.eval_s(i,k+j) : 0;
_vec.load(inds,false);
return _vec;
}
template<typename U=T>
FASTOR_INLINE U eval_s(FASTOR_INDEX i, FASTOR_INDEX k) const {
return fl_expr.eval_s(i,k) ? _expr.eval_s(i,k) : 0;
}
template<typename U=T>
FASTOR_INLINE SIMDVector<U,simd_abi_type> teval(const std::array<int,DIMS>& as) const {
constexpr size_t _Stride = SIMDVector<T,simd_abi_type>::Size;
SIMDVector<U,simd_abi_type> _vec;
U inds[_Stride];
for (FASTOR_INDEX j=0; j<_Stride; ++j)
inds[j] = fl_expr.teval_s(as) ? _expr.teval_s(as) : 0;
_vec.load(inds,false);
return _vec;
}
template<typename U=T>
FASTOR_INLINE U teval_s(const std::array<int,DIMS>& as) const {
return fl_expr.teval_s(as) ? _expr.teval_s(as) : 0;
}
//------------------------------------------------------------------------------------//
};
} // end of namespace Fastor
#endif // TENSOR_FILTER_VIEWS_H

View File

@@ -0,0 +1,681 @@
#ifndef TENSOR_FIXED_VIEWS_1D_H
#define TENSOR_FIXED_VIEWS_1D_H
#include "Fastor/tensor/Tensor.h"
#include "Fastor/tensor/Ranges.h"
#include "Fastor/expressions/linalg_ops/linalg_traits.h"
namespace Fastor {
// 1D const fixed views
//----------------------------------------------------------------------------------------------//
template<typename T, size_t N, int F0, int L0, int S0>
struct TensorConstFixedViewExpr1D<Tensor<T,N>,fseq<F0,L0,S0>,1> :
public AbstractTensor<TensorConstFixedViewExpr1D<Tensor<T,N>,fseq<F0,L0,S0>,1>,1> {
private:
const Tensor<T,N> &_expr;
public:
using scalar_type = T;
using simd_vector_type = typename Tensor<T,N>::simd_vector_type;
using simd_abi_type = typename simd_vector_type::abi_type;
using result_type = Tensor<T,range_detector<F0,L0,S0>::value>;
static constexpr FASTOR_INDEX Dimension = 1;
static constexpr FASTOR_INDEX Stride = simd_vector_type::Size;
static constexpr FASTOR_INLINE FASTOR_INDEX size() { return range_detector<F0,L0,S0>::value;}
static constexpr FASTOR_INLINE FASTOR_INDEX dimension(FASTOR_INDEX ) {return range_detector<F0,L0,S0>::value;}
constexpr const Tensor<T,N>& expr() const {return _expr;}
constexpr FASTOR_INLINE TensorConstFixedViewExpr1D(const Tensor<T,N> &_ex) : _expr(_ex) {}
template<typename U>
FASTOR_INLINE SIMDVector<U,simd_abi_type> eval(FASTOR_INDEX i) const {
SIMDVector<U,simd_abi_type> _vec;
vector_setter(_vec,_expr.data(),S0*i+F0,S0);
return _vec;
}
template<typename U>
constexpr FASTOR_INLINE U eval_s(FASTOR_INDEX i) const {
return _expr.data()[S0*i+F0];
}
template<typename U>
FASTOR_INLINE SIMDVector<U,simd_abi_type> eval(FASTOR_INDEX i, FASTOR_INDEX j) const {
SIMDVector<U,simd_abi_type> _vec;
vector_setter(_vec,_expr.data(),S0*(i+j)+F0,S0);
return _vec;
}
template<typename U>
constexpr FASTOR_INLINE U eval_s(FASTOR_INDEX i, FASTOR_INDEX j) const {
return _expr.data()[S0*(i+j)+F0];
}
template<typename U=T>
FASTOR_INLINE SIMDVector<U,simd_abi_type> teval(const std::array<int,1>& as) const {
SIMDVector<U,simd_abi_type> _vec;
vector_setter(_vec,_expr.data(),S0*as[0]+F0,S0);
return _vec;
}
template<typename U=T>
constexpr FASTOR_INLINE U teval_s(const std::array<int,1>& as) const {
return _expr.data()[S0*as[0]+F0];
}
};
// 1D non-const fixed views
//----------------------------------------------------------------------------------------------//
template<typename T, size_t N, int F0, int L0, int S0>
struct TensorFixedViewExpr1D<Tensor<T,N>,fseq<F0,L0,S0>,1> :
public AbstractTensor<TensorFixedViewExpr1D<Tensor<T,N>,fseq<F0,L0,S0>,1>,1> {
private:
Tensor<T,N> &_expr;
bool _does_alias = false;
constexpr FASTOR_INLINE Tensor<T,N> get_tensor() const {return _expr;}
public:
using scalar_type = T;
using simd_vector_type = typename Tensor<T,N>::simd_vector_type;
using simd_abi_type = typename simd_vector_type::abi_type;
using result_type = Tensor<T,range_detector<F0,L0,S0>::value>;
static constexpr FASTOR_INDEX Dimension = 1;
static constexpr FASTOR_INDEX Stride = simd_vector_type::Size;
static constexpr FASTOR_INLINE FASTOR_INDEX size() {return range_detector<F0,L0,S0>::value;}
static constexpr FASTOR_INLINE FASTOR_INDEX dimension(FASTOR_INDEX i) {return range_detector<F0,L0,S0>::value;}
constexpr const Tensor<T,N>& expr() const {return _expr;}
FASTOR_INLINE TensorFixedViewExpr1D<Tensor<T,N>,fseq<F0,L0,S0>,1>& noalias() {
_does_alias = true;
return *this;
}
constexpr FASTOR_INLINE TensorFixedViewExpr1D(Tensor<T,N> &_ex) : _expr(_ex) {}
//----------------------------------------------------------------------------------//
FASTOR_HINT_INLINE void operator=(const TensorFixedViewExpr1D<Tensor<T,N>,fseq<F0,L0,S0>,1> &other_src) {
#ifndef FASTOR_NO_ALIAS
if (_does_alias) {
_does_alias = false;
// Evaluate this into a temporary
auto tmp_this_tensor = get_tensor();
auto tmp = TensorFixedViewExpr1D<Tensor<T,N>,fseq<F0,L0,S0>,1>(tmp_this_tensor);
// Assign other to temporary
tmp = other_src;
// assign temporary to this
this->operator=(tmp);
return;
}
#endif
#ifndef NDEBUG
FASTOR_ASSERT(other_src.size()==this->size(), "TENSOR SIZE MISMATCH");
// Check if shape of tensors match
for (FASTOR_INDEX i=0; i<Dimension; ++i) {
FASTOR_ASSERT(other_src.dimension(i)==dimension(i), "TENSOR SHAPE MISMATCH");
}
#endif
T *FASTOR_RESTRICT _data = _expr.data();
FASTOR_IF_CONSTEXPR (S0 == 1) {
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec_other = other_src.template eval<T>(i);
_vec_other.store(&_data[i+F0],false);
}
for (; i <size(); i++) {
_data[i+F0] = other_src.template eval_s<T>(i);
}
}
else {
#ifdef FASTOR_USE_VECTORISED_EXPR_ASSIGN
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec_other = other_src.template eval<T>(i);
for (auto j=0; j<SIMDVector<T,simd_abi_type>::Size; ++j) {
_data[S0*(i+j) + F0] = _vec_other[j];
}
}
for (; i <size(); i++) {
_data[S0*i+F0] = other_src.template eval_s<T>(i);
}
#else
for (FASTOR_INDEX i = 0; i <size(); i++) {
_data[S0*i+F0] = other_src.template eval_s<T>(i);
}
#endif
}
}
//----------------------------------------------------------------------------------//
//----------------------------------------------------------------------------------//
template<typename Derived, size_t DIMS, enable_if_t_<requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator=(const AbstractTensor<Derived,DIMS> &other) {
const typename Derived::result_type& tmp = evaluate(other.self());
this->operator=(tmp);
}
template<typename Derived, size_t DIMS, enable_if_t_<!requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator=(const AbstractTensor<Derived,DIMS> &other) {
#ifndef FASTOR_NO_ALIAS
if (_does_alias) {
_does_alias = false;
// Evaluate this into a temporary
auto tmp_this_tensor = get_tensor();
auto tmp = TensorFixedViewExpr1D<Tensor<T,N>,fseq<F0,L0,S0>,1>(tmp_this_tensor);
// Assign other to temporary
tmp = other;
// assign temporary to this
this->operator=(tmp);
return;
}
#endif
const Derived& other_src = other.self();
#ifndef NDEBUG
FASTOR_ASSERT(other_src.size()==this->size(), "TENSOR SIZE MISMATCH");
#endif
T *FASTOR_RESTRICT _data = _expr.data();
FASTOR_IF_CONSTEXPR(is_boolean_expression_v<Derived>) {
for (FASTOR_INDEX i = 0; i <size(); i++) {
_data[S0*i+F0] = other_src.template eval_s<T>(i);
}
return;
}
FASTOR_IF_CONSTEXPR (S0 == 1) {
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec_other = other_src.template eval<T>(i);
_vec_other.store(&_data[i+F0],false);
}
for (; i <size(); i++) {
_data[i+F0] = other_src.template eval_s<T>(i);
}
}
else {
#ifdef FASTOR_USE_VECTORISED_EXPR_ASSIGN
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec_other = other_src.template eval<T>(i);
for (auto j=0; j<SIMDVector<T,simd_abi_type>::Size; ++j) {
_data[S0*(i+j) + F0] = _vec_other[j];
}
}
for (; i <size(); i++) {
_data[S0*i+F0] = other_src.template eval_s<T>(i);
}
#else
for (FASTOR_INDEX i = 0; i <size(); i++) {
_data[S0*i+F0] = other_src.template eval_s<T>(i);
}
#endif
}
}
template<typename Derived, size_t DIMS, enable_if_t_<requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator+=(const AbstractTensor<Derived,DIMS> &other) {
const typename Derived::result_type& tmp = evaluate(other.self());
this->operator+=(tmp);
}
template<typename Derived, size_t DIMS, enable_if_t_<!requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator+=(const AbstractTensor<Derived,DIMS> &other) {
#ifndef FASTOR_NO_ALIAS
if (_does_alias) {
_does_alias = false;
// Evaluate this into a temporary
auto tmp_this_tensor = get_tensor();
auto tmp = TensorFixedViewExpr1D<Tensor<T,N>,fseq<F0,L0,S0>,1>(tmp_this_tensor);
// Assign other to temporary
tmp = other;
// assign temporary to this
this->operator+=(tmp);
return;
}
#endif
const Derived& other_src = other.self();
#ifndef NDEBUG
FASTOR_ASSERT(other_src.size()==this->size(), "TENSOR SIZE MISMATCH");
#endif
T *FASTOR_RESTRICT _data = _expr.data();
FASTOR_IF_CONSTEXPR (S0 == 1) {
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec = this->template eval<T>(i) + other_src.template eval<T>(i);
_vec.store(&_data[i+F0],false);
}
for (; i <size(); i++) {
_data[i+F0] += other_src.template eval_s<T>(i);
}
}
else {
#ifdef FASTOR_USE_VECTORISED_EXPR_ASSIGN
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec_other = other_src.template eval<T>(i);
for (auto j=0; j<SIMDVector<T,simd_abi_type>::Size; ++j) {
_data[S0*(i+j) + F0] += _vec_other[j];
}
}
for (; i <size(); i++) {
_data[S0*i+F0] += other_src.template eval_s<T>(i);
}
#else
for (FASTOR_INDEX i = 0; i <size(); i++) {
_data[S0*i+F0] += other_src.template eval_s<T>(i);
}
#endif
}
}
template<typename Derived, size_t DIMS, enable_if_t_<requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator-=(const AbstractTensor<Derived,DIMS> &other) {
const typename Derived::result_type& tmp = evaluate(other.self());
this->operator-=(tmp);
}
template<typename Derived, size_t DIMS, enable_if_t_<!requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator-=(const AbstractTensor<Derived,DIMS> &other) {
#ifndef FASTOR_NO_ALIAS
if (_does_alias) {
_does_alias = false;
// Evaluate this into a temporary
auto tmp_this_tensor = get_tensor();
auto tmp = TensorFixedViewExpr1D<Tensor<T,N>,fseq<F0,L0,S0>,1>(tmp_this_tensor);
// Assign other to temporary
tmp = other;
// assign temporary to this
this->operator-=(tmp);
return;
}
#endif
const Derived& other_src = other.self();
#ifndef NDEBUG
FASTOR_ASSERT(other_src.size()==this->size(), "TENSOR SIZE MISMATCH");
#endif
T *FASTOR_RESTRICT _data = _expr.data();
FASTOR_IF_CONSTEXPR (S0 == 1) {
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec = this->template eval<T>(i) - other_src.template eval<T>(i);
_vec.store(&_data[i+F0],false);
}
for (; i <size(); i++) {
_data[i+F0] -= other_src.template eval_s<T>(i);
}
}
else {
#ifdef FASTOR_USE_VECTORISED_EXPR_ASSIGN
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec_other = other_src.template eval<T>(i);
for (auto j=0; j<SIMDVector<T,simd_abi_type>::Size; ++j) {
_data[S0*(i+j) + F0] -= _vec_other[j];
}
}
for (; i <size(); i++) {
_data[S0*i+F0] -= other_src.template eval_s<T>(i);
}
#else
for (FASTOR_INDEX i = 0; i <size(); i++) {
_data[S0*i+F0] -= other_src.template eval_s<T>(i);
}
#endif
}
}
template<typename Derived, size_t DIMS, enable_if_t_<requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator*=(const AbstractTensor<Derived,DIMS> &other) {
const typename Derived::result_type& tmp = evaluate(other.self());
this->operator*=(tmp);
}
template<typename Derived, size_t DIMS, enable_if_t_<!requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator*=(const AbstractTensor<Derived,DIMS> &other) {
#ifndef FASTOR_NO_ALIAS
if (_does_alias) {
_does_alias = false;
// Evaluate this into a temporary
auto tmp_this_tensor = get_tensor();
auto tmp = TensorFixedViewExpr1D<Tensor<T,N>,fseq<F0,L0,S0>,1>(tmp_this_tensor);
// Assign other to temporary
tmp = other;
// assign temporary to this
this->operator=(tmp);
return;
}
#endif
const Derived& other_src = other.self();
#ifndef NDEBUG
FASTOR_ASSERT(other_src.size()==this->size(), "TENSOR SIZE MISMATCH");
#endif
T *FASTOR_RESTRICT _data = _expr.data();
FASTOR_IF_CONSTEXPR (S0 == 1) {
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec = this->template eval<T>(i) * other_src.template eval<T>(i);
_vec.store(&_data[i+F0],false);
}
for (; i <size(); i++) {
_data[i+F0] *= other_src.template eval_s<T>(i);
}
}
else {
#ifdef FASTOR_USE_VECTORISED_EXPR_ASSIGN
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec_other = other_src.template eval<T>(i);
for (auto j=0; j<SIMDVector<T,simd_abi_type>::Size; ++j) {
_data[S0*(i+j) + F0] *= _vec_other[j];
}
}
for (; i <size(); i++) {
_data[S0*i+F0] *= other_src.template eval_s<T>(i);
}
#else
for (FASTOR_INDEX i = 0; i <size(); i++) {
_data[S0*i+F0] *= other_src.template eval_s<T>(i);
}
#endif
}
}
template<typename Derived, size_t DIMS, enable_if_t_<requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator/=(const AbstractTensor<Derived,DIMS> &other) {
const typename Derived::result_type& tmp = evaluate(other.self());
this->operator/=(tmp);
}
template<typename Derived, size_t DIMS, enable_if_t_<!requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator/=(const AbstractTensor<Derived,DIMS> &other) {
#ifndef FASTOR_NO_ALIAS
if (_does_alias) {
_does_alias = false;
// Evaluate this into a temporary
auto tmp_this_tensor = get_tensor();
auto tmp = TensorFixedViewExpr1D<Tensor<T,N>,fseq<F0,L0,S0>,1>(tmp_this_tensor);
// Assign other to temporary
tmp = other;
// assign temporary to this
this->operator/=(tmp);
return;
}
#endif
const Derived& other_src = other.self();
#ifndef NDEBUG
FASTOR_ASSERT(other_src.size()==this->size(), "TENSOR SIZE MISMATCH");
#endif
T *FASTOR_RESTRICT _data = _expr.data();
FASTOR_IF_CONSTEXPR (S0 == 1) {
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec = this->template eval<T>(i) / other_src.template eval<T>(i);
_vec.store(&_data[i+F0],false);
}
for (; i <size(); i++) {
_data[i+F0] /= other_src.template eval_s<T>(i);
}
}
else {
#ifdef FASTOR_USE_VECTORISED_EXPR_ASSIGN
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec_other = other_src.template eval<T>(i);
for (auto j=0; j<SIMDVector<T,simd_abi_type>::Size; ++j) {
_data[S0*(i+j) + F0] /= _vec_other[j];
}
}
for (; i <size(); i++) {
_data[S0*i+F0] /= other_src.template eval_s<T>(i);
}
#else
for (FASTOR_INDEX i = 0; i <size(); i++) {
_data[S0*i+F0] /= other_src.template eval_s<T>(i);
}
#endif
}
}
//----------------------------------------------------------------------------------//
// Scalar binders
//----------------------------------------------------------------------------------//
template<typename U=T, enable_if_t_<is_primitive_v_<U>,bool> = false>
FASTOR_HINT_INLINE void operator=(U num) {
simd_vector_type _vec_other(static_cast<T>(num));
T *FASTOR_RESTRICT _data = _expr.data();
FASTOR_IF_CONSTEXPR (S0 == 1) {
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
_vec_other.store(&_data[i+F0],false);
}
for (; i <size(); i++) {
_data[i+F0] = num;
}
}
else {
#ifdef FASTOR_USE_VECTORISED_EXPR_ASSIGN
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
for (auto j=0; j<SIMDVector<T,simd_abi_type>::Size; ++j) {
_data[S0*(i+j) + F0] = _vec_other[j];
}
}
for (; i <size(); i++) {
_data[S0*i+F0] = num;
}
#else
for (FASTOR_INDEX i = 0; i <size(); i++) {
_data[S0*i+F0] = num;
}
#endif
}
}
template<typename U=T, enable_if_t_<is_primitive_v_<U>,bool> = false>
FASTOR_HINT_INLINE void operator+=(U num) {
simd_vector_type _vec_other(static_cast<T>(num));
T *FASTOR_RESTRICT _data = _expr.data();
FASTOR_IF_CONSTEXPR (S0 == 1) {
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec = this->template eval<T>(i) + _vec_other;
_vec.store(&_data[i+F0],false);
}
for (; i <size(); i++) {
_data[i+F0] += num;
}
}
else {
#ifdef FASTOR_USE_VECTORISED_EXPR_ASSIGN
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
for (auto j=0; j<SIMDVector<T,simd_abi_type>::Size; ++j) {
_data[S0*(i+j) + F0] += _vec_other[j];
}
}
for (; i <size(); i++) {
_data[S0*i+F0] += num;
}
#else
for (FASTOR_INDEX i = 0; i <size(); i++) {
_data[S0*i+F0] += num;
}
#endif
}
}
template<typename U=T, enable_if_t_<is_primitive_v_<U>,bool> = false>
FASTOR_HINT_INLINE void operator-=(U num) {
simd_vector_type _vec_other(static_cast<T>(num));
T *FASTOR_RESTRICT _data = _expr.data();
FASTOR_IF_CONSTEXPR (S0 == 1) {
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec = this->template eval<T>(i) - _vec_other;
_vec.store(&_data[i+F0],false);
}
for (; i <size(); i++) {
_data[i+F0] -= num;
}
}
else {
#ifdef FASTOR_USE_VECTORISED_EXPR_ASSIGN
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
for (auto j=0; j<SIMDVector<T,simd_abi_type>::Size; ++j) {
_data[S0*(i+j) + F0] -= _vec_other[j];
}
}
for (; i <size(); i++) {
_data[S0*i+F0] -= num;
}
#else
for (FASTOR_INDEX i = 0; i <size(); i++) {
_data[S0*i+F0] -= num;
}
#endif
}
}
template<typename U=T, enable_if_t_<is_primitive_v_<U>,bool> = false>
FASTOR_HINT_INLINE void operator*=(U num) {
simd_vector_type _vec_other(static_cast<T>(num));
T *FASTOR_RESTRICT _data = _expr.data();
FASTOR_IF_CONSTEXPR (S0 == 1) {
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec = this->template eval<T>(i) * _vec_other;
_vec.store(&_data[i+F0],false);
}
for (; i <size(); i++) {
_data[i+F0] *= num;
}
}
else {
#ifdef FASTOR_USE_VECTORISED_EXPR_ASSIGN
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
for (auto j=0; j<SIMDVector<T,simd_abi_type>::Size; ++j) {
_data[S0*(i+j) + F0] *= _vec_other[j];
}
}
for (; i <size(); i++) {
_data[S0*i+F0] *= num;
}
#else
for (FASTOR_INDEX i = 0; i <size(); i++) {
_data[S0*i+F0] *= num;
}
#endif
}
}
template<typename U=T, enable_if_t_<is_primitive_v_<U> && !is_integral_v_<U>,bool> = false>
FASTOR_HINT_INLINE void operator/=(U num) {
T inum = T(1) / static_cast<T>(num);
simd_vector_type _vec_other(inum);
T *FASTOR_RESTRICT _data = _expr.data();
FASTOR_IF_CONSTEXPR (S0 == 1) {
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec = this->template eval<T>(i) * _vec_other;
_vec.store(&_data[i+F0],false);
}
for (; i <size(); i++) {
_data[i+F0] *= inum;
}
}
else {
#ifdef FASTOR_USE_VECTORISED_EXPR_ASSIGN
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
for (auto j=0; j<SIMDVector<T,simd_abi_type>::Size; ++j) {
_data[S0*(i+j) + F0] *= _vec_other[j];
}
}
for (; i <size(); i++) {
_data[S0*i+F0] *= inum;
}
#else
for (FASTOR_INDEX i = 0; i <size(); i++) {
_data[S0*i+F0] *= inum;
}
#endif
}
}
template<typename U=T, enable_if_t_<is_primitive_v_<U> && is_integral_v_<U>,bool> = false>
FASTOR_HINT_INLINE void operator/=(U num) {
simd_vector_type _vec_other(static_cast<T>(num));
T *FASTOR_RESTRICT _data = _expr.data();
FASTOR_IF_CONSTEXPR (S0 == 1) {
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec = this->template eval<T>(i) / _vec_other;
_vec.store(&_data[i+F0],false);
}
for (; i <size(); i++) {
_data[i+F0] /= num;
}
}
else {
#ifdef FASTOR_USE_VECTORISED_EXPR_ASSIGN
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
for (auto j=0; j<SIMDVector<T,simd_abi_type>::Size; ++j) {
_data[S0*(i+j) + F0] /= _vec_other[j];
}
}
for (; i <size(); i++) {
_data[S0*i+F0] /= num;
}
#else
for (FASTOR_INDEX i = 0; i <size(); i++) {
_data[S0*i+F0] /= num;
}
#endif
}
}
//----------------------------------------------------------------------------------//
template<typename U>
FASTOR_INLINE SIMDVector<U,simd_abi_type> eval(FASTOR_INDEX i) const {
SIMDVector<U,simd_abi_type> _vec;
vector_setter(_vec,_expr.data(),S0*i+F0,S0);
return _vec;
}
template<typename U>
constexpr FASTOR_INLINE U eval_s(FASTOR_INDEX i) const {
return _expr.data()[S0*i+F0];
}
template<typename U>
FASTOR_INLINE SIMDVector<U,simd_abi_type> eval(FASTOR_INDEX i, FASTOR_INDEX j) const {
SIMDVector<U,simd_abi_type> _vec;
vector_setter(_vec,_expr.data(),S0*(i+j)+F0,S0);
return _vec;
}
template<typename U>
constexpr FASTOR_INLINE U eval_s(FASTOR_INDEX i, FASTOR_INDEX j) const {
return _expr.data()[S0*(i+j)+F0];
}
template<typename U=T>
FASTOR_INLINE SIMDVector<U,simd_abi_type> teval(const std::array<int,1>& as) const {
SIMDVector<U,simd_abi_type> _vec;
vector_setter(_vec,_expr.data(),S0*as[0]+F0,S0);
return _vec;
}
template<typename U=T>
constexpr FASTOR_INLINE U teval_s(const std::array<int,1>& as) const {
return _expr.data()[S0*as[0]+F0];
}
};
}
#endif // TENSOR_FIXED_VIEWS_1D_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
#ifndef TENSOR_VIEWS_H
#define TENSOR_VIEWS_H
#include "Fastor/expressions/views/tensor_views_1d.h"
#include "Fastor/expressions/views/tensor_views_2d.h"
#include "Fastor/expressions/views/tensor_views_nd.h"
#include "Fastor/expressions/views/tensor_views_assignment.h"
#endif // TENSOR_VIEWS_H

View File

@@ -0,0 +1,739 @@
#ifndef TENSOR_VIEWS_1D_H
#define TENSOR_VIEWS_1D_H
#include "Fastor/tensor/Tensor.h"
#include "Fastor/tensor/Ranges.h"
#include "Fastor/expressions/linalg_ops/linalg_traits.h"
namespace Fastor {
// 1D const views
//-------------------------------------------------------------------------------------//
template<typename T, size_t N>
struct TensorConstViewExpr<Tensor<T,N>,1>: public AbstractTensor<TensorConstViewExpr<Tensor<T,N>,1>,1> {
private:
const Tensor<T,N> &_expr;
seq _seq;
public:
using scalar_type = T;
using simd_vector_type = typename Tensor<T,N>::simd_vector_type;
using simd_abi_type = typename simd_vector_type::abi_type;
using V = simd_vector_type;
using result_type = Tensor<T,N>;
static constexpr FASTOR_INDEX Dimension = 1;
static constexpr FASTOR_INDEX Stride = simd_vector_type::Size;
static constexpr FASTOR_INDEX rank() {return 1;}
constexpr FASTOR_INLINE FASTOR_INDEX size() const {return _seq.size();}
constexpr FASTOR_INLINE FASTOR_INDEX dimension(FASTOR_INDEX ) const {return _seq.size();}
constexpr const Tensor<T,N>& expr() const {return _expr;}
FASTOR_INLINE TensorConstViewExpr(const Tensor<T,N> &_ex, const seq &_s) : _expr(_ex), _seq(_s) {
if (_seq._last < 0) _seq._last += N + /*including the end point*/ 1;
if (_seq._first < 0) _seq._first += N + /*including the end point*/ 1;
}
template<typename U>
FASTOR_INLINE SIMDVector<U,simd_abi_type> eval(FASTOR_INDEX i) const {
SIMDVector<U,simd_abi_type> _vec;
vector_setter(_vec,_expr.data(),i*_seq._step+_seq._first,_seq._step);
return _vec;
}
template<typename U>
constexpr FASTOR_INLINE U eval_s(FASTOR_INDEX i) const {
return _expr.data()[i*_seq._step+_seq._first];
}
template<typename U>
FASTOR_INLINE SIMDVector<U,simd_abi_type> eval(FASTOR_INDEX i, FASTOR_INDEX j) const {
SIMDVector<U,simd_abi_type> _vec;
vector_setter(_vec,_expr.data(),(i+j)*_seq._step+_seq._first,_seq._step);
return _vec;
}
template<typename U>
constexpr FASTOR_INLINE U eval_s(FASTOR_INDEX i, FASTOR_INDEX j) const {
return _expr.data()[(i+j)*_seq._step+_seq._first];
}
template<typename U=T>
FASTOR_INLINE SIMDVector<U,simd_abi_type> teval(const std::array<int,1>& as) const {
SIMDVector<U,simd_abi_type> _vec;
vector_setter(_vec,_expr.data(),as[0]*_seq._step+_seq._first,_seq._step);
return _vec;
}
template<typename U=T>
constexpr FASTOR_INLINE U teval_s(const std::array<int,1>& as) const {
return _expr.data()[as[0]*_seq._step+_seq._first];
}
};
// 1D non-const views
//-------------------------------------------------------------------------------------//
template<typename T, size_t N>
struct TensorViewExpr<Tensor<T,N>,1>: public AbstractTensor<TensorViewExpr<Tensor<T,N>,1>,1> {
private:
Tensor<T,N> &_expr;
seq _seq;
bool _does_alias = false;
constexpr FASTOR_INLINE Tensor<T,N> get_tensor() const {return _expr;}
public:
using scalar_type = T;
using simd_vector_type = typename Tensor<T,N>::simd_vector_type;
using simd_abi_type = typename simd_vector_type::abi_type;
using V = simd_vector_type;
using result_type = Tensor<T,N>;
static constexpr FASTOR_INDEX Dimension = 1;
static constexpr FASTOR_INDEX Stride = simd_vector_type::Size;
static constexpr FASTOR_INDEX rank() {return 1;}
constexpr FASTOR_INLINE FASTOR_INDEX size() const {return _seq.size();}
constexpr FASTOR_INLINE FASTOR_INDEX dimension(FASTOR_INDEX ) const {return _seq.size();}
constexpr const Tensor<T,N>& expr() const {return _expr;}
FASTOR_INLINE TensorViewExpr<Tensor<T,N>,1>& noalias() {
_does_alias = true;
return *this;
}
FASTOR_INLINE TensorViewExpr(Tensor<T,N> &_ex, const seq &_s) : _expr(_ex), _seq(_s) {
if (_seq._last < 0) _seq._last += N + /*including the end point*/ 1;
if (_seq._first < 0) _seq._first += N + /*including the end point*/ 1;
}
// View evalution operators
// Copy assignment operators [Needed in addition to generic AbstractTensor overload]
//----------------------------------------------------------------------------------//
FASTOR_HINT_INLINE void operator=(const TensorViewExpr<Tensor<T,N>,1> &other) {
#if !(FASTOR_NO_ALIAS)
if (_does_alias) {
_does_alias = false;
// Evaluate this into a temporary
auto tmp_this_tensor = get_tensor();
auto tmp = TensorViewExpr<Tensor<T,N>,1>(tmp_this_tensor,_seq);
// Assign other to temporary
tmp = other;
// assign temporary to this
this->operator=(tmp);
return;
}
#endif
#ifndef NDEBUG
FASTOR_ASSERT(other.size()==this->size(), "TENSOR SIZE MISMATCH");
// Check if shape of tensors match - for this 1D case for loop unnecessary
for (FASTOR_INDEX i=0; i<Dimension; ++i) {
FASTOR_ASSERT(other.dimension(i)==dimension(i), "TENSOR SHAPE MISMATCH");
}
#endif
T *FASTOR_RESTRICT _data = _expr.data();
if (_seq._step == 1) {
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec = other.template eval<T>(i);
_vec.store(&_data[i+_seq._first],false);
}
for (; i <size(); i++) {
_data[i+_seq._first] = other.template eval_s<T>(i);
}
}
else {
#ifdef FASTOR_USE_VECTORISED_EXPR_ASSIGN
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec_other = other.template eval<T>(i);
for (auto j=0; j<simd_vector_type::Size; ++j) {
auto idx = (i+j)*_seq._step+_seq._first;
_data[idx] = _vec_other[j];
}
}
for (; i <size(); i++) {
auto idx = i*_seq._step+_seq._first;
_data[idx] = other.template eval_s<T>(i);
}
#else
for (FASTOR_INDEX i = 0; i <size(); i++) {
auto idx = i*_seq._step+_seq._first;
_data[idx] = other.template eval_s<T>(i);
}
#endif
}
}
//----------------------------------------------------------------------------------//
// AbstractTensor binders
//----------------------------------------------------------------------------------//
template<typename Derived, size_t DIMS, enable_if_t_<requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator=(const AbstractTensor<Derived,DIMS> &other) {
const typename Derived::result_type& tmp = evaluate(other.self());
this->operator=(tmp);
}
template<typename Derived, size_t DIMS, enable_if_t_<!requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator=(const AbstractTensor<Derived,DIMS> &other) {
#if !(FASTOR_NO_ALIAS)
if (_does_alias) {
_does_alias = false;
// Evaluate this into a temporary
auto tmp_this_tensor = get_tensor();
auto tmp = TensorViewExpr<Tensor<T,N>,1>(tmp_this_tensor,_seq);
// Assign other to temporary
tmp = other;
// assign temporary to this
this->operator=(tmp);
return;
}
#endif
const Derived& other_src = other.self();
#ifndef NDEBUG
FASTOR_ASSERT(other_src.size()==this->size(), "TENSOR SIZE MISMATCH");
#endif
T *FASTOR_RESTRICT _data = _expr.data();
FASTOR_IF_CONSTEXPR(is_boolean_expression_v<Derived>) {
for (FASTOR_INDEX i = 0; i <size(); i++) {
auto idx = i*_seq._step+_seq._first;
_data[idx] = other_src.template eval_s<T>(i);
}
return;
}
if (_seq._step == 1) {
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec = other_src.template eval<T>(i);
_vec.store(&_data[i+_seq._first],false);
}
for (; i <size(); i++) {
_data[i+_seq._first] = other_src.template eval_s<T>(i);
}
}
else {
#ifdef FASTOR_USE_VECTORISED_EXPR_ASSIGN
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec_other = other_src.template eval<T>(i);
for (auto j=0; j<simd_vector_type::Size; ++j) {
auto idx = (i+j)*_seq._step+_seq._first;
_data[idx] = _vec_other[j];
}
}
for (; i <size(); i++) {
auto idx = i*_seq._step+_seq._first;
_data[idx] = other_src.template eval_s<T>(i);
}
#else
for (FASTOR_INDEX i = 0; i <size(); i++) {
auto idx = i*_seq._step+_seq._first;
_data[idx] = other_src.template eval_s<T>(i);
}
#endif
}
}
template<typename Derived, size_t DIMS, enable_if_t_<requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator+=(const AbstractTensor<Derived,DIMS> &other) {
const typename Derived::result_type& tmp = evaluate(other.self());
this->operator+=(tmp);
}
template<typename Derived, size_t DIMS, enable_if_t_<!requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator+=(const AbstractTensor<Derived,DIMS> &other) {
#if !(FASTOR_NO_ALIAS)
if (_does_alias) {
_does_alias = false;
// Evaluate this into a temporary
auto tmp_this_tensor = get_tensor();
auto tmp = TensorViewExpr<Tensor<T,N>,1>(tmp_this_tensor,_seq);
// Assign other to temporary
tmp = other;
// assign temporary to this
this->operator+=(tmp);
return;
}
#endif
const Derived& other_src = other.self();
#ifndef NDEBUG
FASTOR_ASSERT(other_src.size()==this->size(), "TENSOR SIZE MISMATCH");
#endif
T *FASTOR_RESTRICT _data = _expr.data();
if (_seq._step == 1) {
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec = this->template eval<T>(i) + other_src.template eval<T>(i);
_vec.store(&_data[i+_seq._first],false);
}
for (; i <size(); i++) {
_data[i+_seq._first] += other_src.template eval_s<T>(i);
}
}
else {
#ifdef FASTOR_USE_VECTORISED_EXPR_ASSIGN
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec_other = other_src.template eval<T>(i);
for (auto j=0; j<simd_vector_type::Size; ++j) {
auto idx = (i+j)*_seq._step+_seq._first;
_data[idx] += _vec_other[j];
}
}
for (; i <size(); i++) {
auto idx = i*_seq._step+_seq._first;
_data[idx] += other_src.template eval_s<T>(i);
}
#else
for (FASTOR_INDEX i = 0; i <size(); i++) {
auto idx = i*_seq._step+_seq._first;
_data[idx] += other_src.template eval_s<T>(i);
}
#endif
}
}
template<typename Derived, size_t DIMS, enable_if_t_<requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator-=(const AbstractTensor<Derived,DIMS> &other) {
const typename Derived::result_type& tmp = evaluate(other.self());
this->operator-=(tmp);
}
template<typename Derived, size_t DIMS, enable_if_t_<!requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator-=(const AbstractTensor<Derived,DIMS> &other) {
#if !(FASTOR_NO_ALIAS)
if (_does_alias) {
_does_alias = false;
// Evaluate this into a temporary
auto tmp_this_tensor = get_tensor();
auto tmp = TensorViewExpr<Tensor<T,N>,1>(tmp_this_tensor,_seq);
// Assign other to temporary
tmp = other;
// assign temporary to this
this->operator-=(tmp);
return;
}
#endif
const Derived& other_src = other.self();
#ifndef NDEBUG
FASTOR_ASSERT(other_src.size()==this->size(), "TENSOR SIZE MISMATCH");
#endif
T *FASTOR_RESTRICT _data = _expr.data();
if (_seq._step == 1) {
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec = this->template eval<T>(i) - other_src.template eval<T>(i);
_vec.store(&_data[i+_seq._first],false);
}
for (; i <size(); i++) {
_data[i+_seq._first] -= other_src.template eval_s<T>(i);
}
}
else {
#ifdef FASTOR_USE_VECTORISED_EXPR_ASSIGN
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec_other = other_src.template eval<T>(i);
for (auto j=0; j<simd_vector_type::Size; ++j) {
auto idx = (i+j)*_seq._step+_seq._first;
_data[idx] -= _vec_other[j];
}
}
for (; i <size(); i++) {
auto idx = i*_seq._step+_seq._first;
_data[idx] -= other_src.template eval_s<T>(i);
}
#else
for (FASTOR_INDEX i = 0; i <size(); i++) {
auto idx = i*_seq._step+_seq._first;
_data[idx] -= other_src.template eval_s<T>(i);
}
#endif
}
}
template<typename Derived, size_t DIMS, enable_if_t_<requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator*=(const AbstractTensor<Derived,DIMS> &other) {
const typename Derived::result_type& tmp = evaluate(other.self());
this->operator*=(tmp);
}
template<typename Derived, size_t DIMS, enable_if_t_<!requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator*=(const AbstractTensor<Derived,DIMS> &other) {
#if !(FASTOR_NO_ALIAS)
if (_does_alias) {
_does_alias = false;
// Evaluate this into a temporary
auto tmp_this_tensor = get_tensor();
auto tmp = TensorViewExpr<Tensor<T,N>,1>(tmp_this_tensor,_seq);
// Assign other to temporary
tmp = other;
// assign temporary to this
this->operator*=(tmp);
return;
}
#endif
const Derived& other_src = other.self();
#ifndef NDEBUG
FASTOR_ASSERT(other_src.size()==this->size(), "TENSOR SIZE MISMATCH");
#endif
T *FASTOR_RESTRICT _data = _expr.data();
if (_seq._step == 1) {
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec = this->template eval<T>(i) * other_src.template eval<T>(i);
_vec.store(&_data[i+_seq._first],false);
}
for (; i <size(); i++) {
_data[i+_seq._first] *= other_src.template eval_s<T>(i);
}
}
else {
#ifdef FASTOR_USE_VECTORISED_EXPR_ASSIGN
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec_other = other_src.template eval<T>(i);
for (auto j=0; j<simd_vector_type::Size; ++j) {
auto idx = (i+j)*_seq._step+_seq._first;
_data[idx] *= _vec_other[j];
}
}
for (; i <size(); i++) {
auto idx = i*_seq._step+_seq._first;
_data[idx] *= other_src.template eval_s<T>(i);
}
#else
for (FASTOR_INDEX i = 0; i <size(); i++) {
auto idx = i*_seq._step+_seq._first;
_data[idx] *= other_src.template eval_s<T>(i);
}
#endif
}
}
template<typename Derived, size_t DIMS, enable_if_t_<requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator/=(const AbstractTensor<Derived,DIMS> &other) {
const typename Derived::result_type& tmp = evaluate(other.self());
this->operator/=(tmp);
}
template<typename Derived, size_t DIMS, enable_if_t_<!requires_evaluation_v<Derived>,bool> = false>
FASTOR_HINT_INLINE void operator/=(const AbstractTensor<Derived,DIMS> &other) {
#if !(FASTOR_NO_ALIAS)
if (_does_alias) {
_does_alias = false;
// Evaluate this into a temporary
auto tmp_this_tensor = get_tensor();
auto tmp = TensorViewExpr<Tensor<T,N>,1>(tmp_this_tensor,_seq);
// Assign other to temporary
tmp = other;
// assign temporary to this
this->operator/=(tmp);
return;
}
#endif
const Derived& other_src = other.self();
#ifndef NDEBUG
FASTOR_ASSERT(other_src.size()==this->size(), "TENSOR SIZE MISMATCH");
#endif
T *FASTOR_RESTRICT _data = _expr.data();
if (_seq._step == 1) {
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec = this->template eval<T>(i) / other_src.template eval<T>(i);
_vec.store(&_data[i+_seq._first],false);
}
for (; i <size(); i++) {
_data[i+_seq._first] /= other_src.template eval_s<T>(i);
}
}
else {
#ifdef FASTOR_USE_VECTORISED_EXPR_ASSIGN
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec_other = other_src.template eval<T>(i);
for (auto j=0; j<simd_vector_type::Size; ++j) {
auto idx = (i+j)*_seq._step+_seq._first;
_data[idx] /= _vec_other[j];
}
}
for (; i <size(); i++) {
auto idx = i*_seq._step+_seq._first;
_data[idx] /= other_src.template eval_s<T>(i);
}
#else
for (FASTOR_INDEX i = 0; i <size(); i++) {
auto idx = i*_seq._step+_seq._first;
_data[idx] /= other_src.template eval_s<T>(i);
}
#endif
}
}
//----------------------------------------------------------------------------------//
// scalar binders
//----------------------------------------------------------------------------------//
template<typename U=T, enable_if_t_<is_primitive_v_<U>,bool> = false>
FASTOR_HINT_INLINE void operator=(U num) {
simd_vector_type _vec_other(static_cast<T>(num));
T *FASTOR_RESTRICT _data = _expr.data();
if (_seq._step == 1) {
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
_vec_other.store(&_data[i+_seq._first],false);
}
for (; i <size(); i++) {
_data[i+_seq._first] = num;
}
}
else {
#ifdef FASTOR_USE_VECTORISED_EXPR_ASSIGN
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
for (auto j=0; j<simd_vector_type::Size; ++j) {
auto idx = (i+j)*_seq._step+_seq._first;
_data[idx] = _vec_other[j];
}
}
for (; i <size(); i++) {
auto idx = i*_seq._step+_seq._first;
_data[idx] = num;
}
#else
for (FASTOR_INDEX i = 0; i <size(); i++) {
auto idx = i*_seq._step+_seq._first;
_data[idx] = num;
}
#endif
}
}
template<typename U=T, enable_if_t_<is_primitive_v_<U>,bool> = false>
FASTOR_HINT_INLINE void operator+=(U num) {
simd_vector_type _vec_other(static_cast<T>(num));
T *FASTOR_RESTRICT _data = _expr.data();
if (_seq._step == 1) {
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec = this->template eval<T>(i) + _vec_other;
_vec.store(&_data[i+_seq._first],false);
}
for (; i <size(); i++) {
_data[i+_seq._first] += num;
}
}
else {
#ifdef FASTOR_USE_VECTORISED_EXPR_ASSIGN
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
for (auto j=0; j<simd_vector_type::Size; ++j) {
auto idx = (i+j)*_seq._step+_seq._first;
_data[idx] += _vec_other[j];
}
}
for (; i <size(); i++) {
auto idx = i*_seq._step+_seq._first;
_data[idx] += num;
}
#else
for (FASTOR_INDEX i = 0; i <size(); i++) {
auto idx = i*_seq._step+_seq._first;
_data[idx] += num;
}
#endif
}
}
template<typename U=T, enable_if_t_<is_primitive_v_<U>,bool> = false>
FASTOR_HINT_INLINE void operator-=(U num) {
simd_vector_type _vec_other(static_cast<T>(num));
T *FASTOR_RESTRICT _data = _expr.data();
if (_seq._step == 1) {
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec = this->template eval<T>(i) - _vec_other;
_vec.store(&_data[i+_seq._first],false);
}
for (; i <size(); i++) {
_data[i+_seq._first] -= num;
}
}
else {
#ifdef FASTOR_USE_VECTORISED_EXPR_ASSIGN
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
for (auto j=0; j<simd_vector_type::Size; ++j) {
auto idx = (i+j)*_seq._step+_seq._first;
_data[idx] -= _vec_other[j];
}
}
for (; i <size(); i++) {
auto idx = i*_seq._step+_seq._first;
_data[idx] -= num;
}
#else
for (FASTOR_INDEX i = 0; i <size(); i++) {
auto idx = i*_seq._step+_seq._first;
_data[idx] -= num;
}
#endif
}
}
template<typename U=T, enable_if_t_<is_primitive_v_<U>,bool> = false>
FASTOR_HINT_INLINE void operator*=(U num) {
simd_vector_type _vec_other(static_cast<T>(num));
T *FASTOR_RESTRICT _data = _expr.data();
if (_seq._step == 1) {
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec = this->template eval<T>(i) * _vec_other;
_vec.store(&_data[i+_seq._first],false);
}
for (; i <size(); i++) {
_data[i+_seq._first] *= num;
}
}
else {
#ifdef FASTOR_USE_VECTORISED_EXPR_ASSIGN
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
for (auto j=0; j<simd_vector_type::Size; ++j) {
auto idx = (i+j)*_seq._step+_seq._first;
_data[idx] *= _vec_other[j];
}
}
for (; i <size(); i++) {
auto idx = i*_seq._step+_seq._first;
_data[idx] *= num;
}
#else
for (FASTOR_INDEX i = 0; i <size(); i++) {
auto idx = i*_seq._step+_seq._first;
_data[idx] *= num;
}
#endif
}
}
template<typename U=T, enable_if_t_<is_primitive_v_<U> && !is_integral_v_<U>,bool> = false>
FASTOR_HINT_INLINE void operator/=(U num) {
T inum = T(1) / static_cast<T>(num);
simd_vector_type _vec_other(inum);
T *FASTOR_RESTRICT _data = _expr.data();
if (_seq._step == 1) {
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec = this->template eval<T>(i) * _vec_other;
_vec.store(&_data[i+_seq._first],false);
}
for (; i <size(); i++) {
_data[i+_seq._first] *= inum;
}
}
else {
#ifdef FASTOR_USE_VECTORISED_EXPR_ASSIGN
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
for (auto j=0; j<simd_vector_type::Size; ++j) {
auto idx = (i+j)*_seq._step+_seq._first;
_data[idx] *= _vec_other[j];
}
}
for (; i <size(); i++) {
auto idx = i*_seq._step+_seq._first;
_data[idx] *= inum;
}
#else
for (FASTOR_INDEX i = 0; i <size(); i++) {
auto idx = i*_seq._step+_seq._first;
_data[idx] *= inum;
}
#endif
}
}
template<typename U=T, enable_if_t_<is_primitive_v_<U> && is_integral_v_<U>,bool> = false>
FASTOR_HINT_INLINE void operator/=(U num) {
simd_vector_type _vec_other(static_cast<T>(num));
T *FASTOR_RESTRICT _data = _expr.data();
if (_seq._step == 1) {
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
auto _vec = this->template eval<T>(i) / _vec_other;
_vec.store(&_data[i+_seq._first],false);
}
for (; i <size(); i++) {
_data[i+_seq._first] /= num;
}
}
else {
#ifdef FASTOR_USE_VECTORISED_EXPR_ASSIGN
FASTOR_INDEX i;
for (i = 0; i <ROUND_DOWN(size(),Stride); i+=Stride) {
for (auto j=0; j<simd_vector_type::Size; ++j) {
auto idx = (i+j)*_seq._step+_seq._first;
_data[idx] /= _vec_other[j];
}
}
for (; i <size(); i++) {
auto idx = i*_seq._step+_seq._first;
_data[idx] /= num;
}
#else
for (FASTOR_INDEX i = 0; i <size(); i++) {
auto idx = i*_seq._step+_seq._first;
_data[idx] /= num;
}
#endif
}
}
//----------------------------------------------------------------------------------//
template<typename U>
FASTOR_INLINE SIMDVector<U,simd_abi_type> eval(FASTOR_INDEX i) const {
SIMDVector<U,simd_abi_type> _vec;
vector_setter(_vec,_expr.data(),i*_seq._step+_seq._first,_seq._step);
return _vec;
}
template<typename U>
constexpr FASTOR_INLINE U eval_s(FASTOR_INDEX i) const {
return _expr.data()[i*_seq._step+_seq._first];
}
template<typename U>
FASTOR_INLINE SIMDVector<U,simd_abi_type> eval(FASTOR_INDEX i, FASTOR_INDEX j) const {
SIMDVector<U,simd_abi_type> _vec;
vector_setter(_vec,_expr.data(),(i+j)*_seq._step+_seq._first,_seq._step);
return _vec;
}
template<typename U>
constexpr FASTOR_INLINE U eval_s(FASTOR_INDEX i, FASTOR_INDEX j) const {
return _expr.data()[(i+j)*_seq._step+_seq._first];
}
template<typename U=T>
FASTOR_INLINE SIMDVector<U,simd_abi_type> teval(const std::array<int,1>& as) const {
SIMDVector<U,simd_abi_type> _vec;
vector_setter(_vec,_expr.data(),as[0]*_seq._step+_seq._first,_seq._step);
return _vec;
}
template<typename U=T>
constexpr FASTOR_INLINE U teval_s(const std::array<int,1>& as) const {
return _expr.data()[as[0]*_seq._step+_seq._first];
}
};
} // end of namespace Fastor
#endif // TENSOR_VIEWS_1D_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,72 @@
#ifndef TENSOR_VIEWS_ASSIGNMENT_H
#define TENSOR_VIEWS_ASSIGNMENT_H
#include "Fastor/expressions/views/tensor_views.h"
#include "Fastor/expressions/views/tensor_fixed_views_1d.h"
#include "Fastor/expressions/views/tensor_fixed_views_2d.h"
#include "Fastor/expressions/views/tensor_random_views.h"
namespace Fastor {
#define FASTOR_MAKE_ALL_TENSOR_VIEWS_ASSIGNMENT(ASSIGN_TYPE)\
template<typename Derived, size_t DIM, typename TensorType, typename Seq>\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const TensorConstFixedViewExpr1D<TensorType,Seq,1>& src) {\
trivial_assign ##ASSIGN_TYPE (dst.self(), src.self());\
}\
template<typename Derived, size_t DIM, typename TensorType, typename Seq>\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const TensorFixedViewExpr1D<TensorType,Seq,1>& src) {\
trivial_assign ##ASSIGN_TYPE (dst.self(), src.self());\
}\
template<typename Derived, size_t DIM, typename TensorType, typename Seq0, typename Seq1>\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const TensorConstFixedViewExpr2D<TensorType,Seq0,Seq1,2>& src) {\
trivial_assign ##ASSIGN_TYPE (dst.self(), src.self());\
}\
template<typename Derived, size_t DIM, typename TensorType, typename Seq0, typename Seq1>\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const TensorFixedViewExpr2D<TensorType,Seq0,Seq1,2>& src) {\
trivial_assign ##ASSIGN_TYPE (dst.self(), src.self());\
}\
template<typename Derived, size_t DIM, typename TensorType, typename ... Fseq>\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const TensorConstFixedViewExprnD<TensorType,Fseq...>& src) {\
trivial_assign ##ASSIGN_TYPE (dst.self(), src.self());\
}\
template<typename Derived, size_t DIM, typename TensorType, typename ... Fseq>\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const TensorFixedViewExprnD<TensorType,Fseq...>& src) {\
trivial_assign ##ASSIGN_TYPE (dst.self(), src.self());\
}\
template<typename Derived, size_t DIM, typename TensorType, size_t OtherDIM>\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const TensorConstViewExpr<TensorType,OtherDIM>& src) {\
trivial_assign ##ASSIGN_TYPE (dst.self(), src.self());\
}\
template<typename Derived, size_t DIM, typename TensorType, size_t OtherDIM>\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const TensorViewExpr<TensorType,OtherDIM>& src) {\
trivial_assign ##ASSIGN_TYPE (dst.self(), src.self());\
}\
template<typename Derived, size_t DIM, typename TensorType, typename TensorIndexType>\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const TensorConstRandomViewExpr<TensorType,TensorIndexType,DIM>& src) {\
trivial_assign ##ASSIGN_TYPE (dst.self(), src.self());\
}\
template<typename Derived, size_t DIM, typename TensorType, typename TensorIndexType>\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const TensorRandomViewExpr<TensorType,TensorIndexType,DIM>& src) {\
trivial_assign ##ASSIGN_TYPE (dst.self(), src.self());\
}\
template<typename Derived, size_t DIM, typename TensorType, typename TensorIndexType>\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const TensorFilterViewExpr<TensorType,TensorIndexType,DIM>& src) {\
trivial_assign ##ASSIGN_TYPE (dst.self(), src.self());\
}\
template<typename Derived, size_t DIM, typename TensorType, size_t OtherDIM>\
FASTOR_INLINE void assign ##ASSIGN_TYPE (AbstractTensor<Derived,DIM> &dst, const TensorDiagViewExpr<TensorType,OtherDIM>& src) {\
trivial_assign ##ASSIGN_TYPE (dst.self(), src.self());\
}\
FASTOR_MAKE_ALL_TENSOR_VIEWS_ASSIGNMENT( )
FASTOR_MAKE_ALL_TENSOR_VIEWS_ASSIGNMENT(_add)
FASTOR_MAKE_ALL_TENSOR_VIEWS_ASSIGNMENT(_sub)
FASTOR_MAKE_ALL_TENSOR_VIEWS_ASSIGNMENT(_mul)
FASTOR_MAKE_ALL_TENSOR_VIEWS_ASSIGNMENT(_div)
} // end of namespace Fastor
#endif // TENSOR_VIEWS_ASSIGNMENT_H

File diff suppressed because it is too large Load Diff