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,374 @@
#ifndef SPECIALISED_CONSTRUCTORS_H
#define SPECIALISED_CONSTRUCTORS_H
//----------------------------------------------------------------------------------------------------------//
template<size_t ...Rest1, typename Seq0, typename Seq1,
typename std::enable_if<sizeof...(Rest)==sizeof...(Rest1),bool>::type=0>
FASTOR_INLINE Tensor(const TensorFixedViewExpr2D<Tensor<T,Rest1...>,Seq0,Seq1,2>& src) {
using scalar_type_ = T;
constexpr FASTOR_INDEX Stride_ = simd_size_v<scalar_type_>;
#ifndef NDEBUG
FASTOR_ASSERT(src.size()==this->size(), "TENSOR SIZE MISMATCH");
for (FASTOR_INDEX i = 0; i<sizeof...(Rest); ++i) {
FASTOR_ASSERT(src.dimension(i)==this->dimension(i), "TENSOR SHAPE MISMATCH");
}
#endif
constexpr FASTOR_INDEX M = get_value<1,Rest...>::value;
constexpr FASTOR_INDEX N = get_value<2,Rest...>::value;
for (FASTOR_INDEX i = 0; i <M; ++i) {
FASTOR_INDEX j;
for (j = 0; j <ROUND_DOWN(N,Stride_); j+=Stride_) {
src.template eval<scalar_type_>(i,j).store(&_data[i*N+j], false);
}
for (; j < N; ++j) {
_data[i*N+j] = src.template eval_s<scalar_type_>(i,j);
}
}
}
template<size_t ...Rest1, typename ... Fseqs, enable_if_t_<sizeof...(Rest1)==sizeof...(Rest),bool> = false>
FASTOR_INLINE Tensor(const TensorFixedViewExprnD<Tensor<T,Rest1...>,Fseqs...>& src) {
#ifndef NDEBUG
FASTOR_ASSERT(src.size()==this->size(), "TENSOR SIZE MISMATCH");
#endif
constexpr int DimensionHolder[dimension_t::value] = {Rest...};
std::array<int,dimension_t::value> as = {};
int jt, counter=0;
if (src.is_vectorisable() || src.is_strided_vectorisable())
{
using V = SIMDVector<T,simd_abi_type>;
V _vec;
while(counter < size())
{
_vec = src.template teval<T>(as);
_vec.store(&_data[counter],false);
counter+=V::Size;
for(jt = dimension_t::value-1; jt>=0; jt--)
{
if (jt == dimension_t::value-1) as[jt]+=V::Size;
else as[jt] +=1;
if(as[jt]<DimensionHolder[jt])
break;
else
as[jt]=0;
}
if(jt<0)
break;
}
}
else {
while(counter < size())
{
_data[counter] = src.template teval_s<T>(as);
counter++;
for(jt = dimension_t::value-1; jt>=0; jt--)
{
as[jt] +=1;
if(as[jt]<DimensionHolder[jt])
break;
else
as[jt]=0;
}
if(jt<0)
break;
}
}
}
#ifndef FASTOR_DISABLE_SPECIALISED_CTR
template<typename Derived, size_t DIMS,
enable_if_t_<!has_tensor_view_v<Derived> && !has_tensor_fixed_view_nd_v<Derived> && has_tensor_fixed_view_2d_v<Derived>
&& DIMS==sizeof...(Rest)
&& requires_evaluation_v<Derived>,bool> = false>
FASTOR_INLINE Tensor(const AbstractTensor<Derived,DIMS>& src_) {
// const typename Derived::result_type& tmp = evaluate(src_.self());
FASTOR_ASSERT(src_.self().size()==this->size(), "TENSOR SIZE MISMATCH");
assign(*this,src_.self());
}
template<typename Derived, size_t DIMS,
enable_if_t_<!has_tensor_view_v<Derived> && !has_tensor_fixed_view_nd_v<Derived> && has_tensor_fixed_view_2d_v<Derived>
&& DIMS==sizeof...(Rest)
&& !requires_evaluation_v<Derived>,bool> = false>
FASTOR_INLINE Tensor(const AbstractTensor<Derived,DIMS>& src_) {
using scalar_type_ = typename scalar_type_finder<Derived>::type;
constexpr FASTOR_INDEX Stride_ = simd_size_v<scalar_type_>;
const Derived &src = src_.self();
#ifndef NDEBUG
FASTOR_ASSERT(src.size()==this->size(), "TENSOR SIZE MISMATCH");
for (FASTOR_INDEX i = 0; i<sizeof...(Rest); ++i) {
FASTOR_ASSERT(src.dimension(i)==this->dimension(i), "TENSOR SHAPE MISMATCH");
}
#endif
constexpr FASTOR_INDEX M = get_value<1,Rest...>::value;
constexpr FASTOR_INDEX N = get_value<2,Rest...>::value;
FASTOR_IF_CONSTEXPR(!is_boolean_expression_v<Derived>) {
for (FASTOR_INDEX i = 0; i <M; ++i) {
FASTOR_INDEX j;
for (j = 0; j <ROUND_DOWN(N,Stride_); j+=Stride_) {
src.template eval<T>(i,j).store(&_data[i*N+j], false);
}
for (; j <N; ++j) {
_data[i*N+j] = src.template eval_s<T>(i,j);
}
}
}
else {
for (FASTOR_INDEX i = 0; i <M; ++i) {
for (FASTOR_INDEX j = 0; j <N; ++j) {
_data[i*N+j] = src.template eval_s<T>(i,j);
}
}
}
}
template<typename Derived, size_t DIMS, enable_if_t_<!has_tensor_view_v<Derived> && has_tensor_fixed_view_nd_v<Derived>
&& DIMS!=2 && DIMS==sizeof...(Rest) &&
requires_evaluation_v<Derived>,bool> = false>
FASTOR_INLINE Tensor(const AbstractTensor<Derived,DIMS>& src_) {
FASTOR_ASSERT(src_.self().size()==this->size(), "TENSOR SIZE MISMATCH");
assign(*this,src_.self());
}
template<typename Derived, size_t DIMS, enable_if_t_<!has_tensor_view_v<Derived> && has_tensor_fixed_view_nd_v<Derived>
&& DIMS!=2 && DIMS==sizeof...(Rest) &&
!requires_evaluation_v<Derived>,bool> = false>
FASTOR_INLINE Tensor(const AbstractTensor<Derived,DIMS>& src_) {
const Derived &src = src_.self();
#ifndef NDEBUG
FASTOR_ASSERT(src.size()==this->size(), "TENSOR SIZE MISMATCH");
for (FASTOR_INDEX i = 0; i<sizeof...(Rest); ++i) {
FASTOR_ASSERT(src.dimension(i)==this->dimension(i), "TENSOR SHAPE MISMATCH");
}
#endif
constexpr int DimensionHolder[dimension_t::value] = {Rest...};
std::array<int,dimension_t::value> as = {};
int jt, counter=0;
while(counter < size())
{
_data[counter] = src.template teval_s<T>(as);
counter++;
for(jt = dimension_t::value-1; jt>=0; jt--)
{
as[jt] +=1;
if(as[jt]<DimensionHolder[jt])
break;
else
as[jt]=0;
}
if(jt<0)
break;
}
}
#endif // FASTOR_DISABLE_SPECIALISED_CTR
//----------------------------------------------------------------------------------------------------------//
//----------------------------------------------------------------------------------------------------------//
template<size_t ...Rest1, enable_if_t_<sizeof...(Rest)==sizeof...(Rest1),bool> = false>
FASTOR_INLINE Tensor(const TensorViewExpr<Tensor<T,Rest1...>,2>& src) {
using scalar_type_ = T;
constexpr FASTOR_INDEX Stride_ = simd_size_v<scalar_type_>;
#ifndef NDEBUG
FASTOR_ASSERT(src.size()==this->size(), "TENSOR SIZE MISMATCH");
for (FASTOR_INDEX i = 0; i<sizeof...(Rest); ++i) {
FASTOR_ASSERT(src.dimension(i)==this->dimension(i), "TENSOR SHAPE MISMATCH");
}
#endif
constexpr FASTOR_INDEX M = get_value<1,Rest...>::value;
constexpr FASTOR_INDEX N = get_value<2,Rest...>::value;
for (FASTOR_INDEX i = 0; i <M; ++i) {
FASTOR_INDEX j;
for (j = 0; j <ROUND_DOWN(N,Stride_); j+=Stride_) {
src.template eval<scalar_type_>(i,j).store(&_data[i*N+j], false);
}
for (; j < N; ++j) {
_data[i*N+j] = src.template eval_s<scalar_type_>(i,j);
}
}
}
template<size_t ...Rest1, enable_if_t_<is_greater<sizeof...(Rest1),2>::value,bool> = false>
FASTOR_INLINE Tensor(const TensorViewExpr<Tensor<T,Rest1...>,sizeof...(Rest)>& src) {
#ifndef NDEBUG
FASTOR_ASSERT(src.size()==this->size(), "TENSOR SIZE MISMATCH");
for (FASTOR_INDEX i = 0; i<sizeof...(Rest); ++i) {
FASTOR_ASSERT(src.dimension(i)==this->dimension(i), "TENSOR SHAPE MISMATCH");
}
#endif
constexpr int DimensionHolder[dimension_t::value] = {Rest...};
std::array<int,dimension_t::value> as = {};
int jt, counter=0;
if (src.is_vectorisable() || src.is_strided_vectorisable())
{
using V = SIMDVector<T,simd_abi_type>;
V _vec;
while(counter < size())
{
_vec = src.template teval<T>(as);
_vec.store(&_data[counter],false);
counter+=V::Size;
for(jt = dimension_t::value-1; jt>=0; jt--)
{
if (jt == dimension_t::value-1) as[jt]+=V::Size;
else as[jt] +=1;
if(as[jt]<DimensionHolder[jt])
break;
else
as[jt]=0;
}
if(jt<0)
break;
}
}
else {
while(counter < size())
{
_data[counter] = src.template teval_s<T>(as);
counter++;
for(jt = dimension_t::value-1; jt>=0; jt--)
{
as[jt] +=1;
if(as[jt]<DimensionHolder[jt])
break;
else
as[jt]=0;
}
if(jt<0)
break;
}
}
}
#ifndef FASTOR_DISABLE_SPECIALISED_CTR
template<typename Derived, size_t DIMS, enable_if_t_<has_tensor_view_v<Derived> && DIMS==2 && DIMS==sizeof...(Rest) &&
requires_evaluation_v<Derived>,bool> = false>
FASTOR_INLINE Tensor(const AbstractTensor<Derived,DIMS>& src_) {
FASTOR_ASSERT(src_.self().size()==this->size(), "TENSOR SIZE MISMATCH");
assign(*this,src_.self());
}
template<typename Derived, size_t DIMS, enable_if_t_<has_tensor_view_v<Derived> && DIMS==2 && DIMS==sizeof...(Rest) &&
!requires_evaluation_v<Derived>,bool> = false>
FASTOR_INLINE Tensor(const AbstractTensor<Derived,DIMS>& src_) {
using scalar_type_ = typename scalar_type_finder<Derived>::type;
constexpr FASTOR_INDEX Stride_ = simd_size_v<scalar_type_>;
const Derived &src = src_.self();
#ifndef NDEBUG
FASTOR_ASSERT(src.size()==this->size(), "TENSOR SIZE MISMATCH");
for (FASTOR_INDEX i = 0; i<sizeof...(Rest); ++i) {
FASTOR_ASSERT(src.dimension(i)==this->dimension(i), "TENSOR SHAPE MISMATCH");
}
#endif
constexpr FASTOR_INDEX M = get_value<1,Rest...>::value;
constexpr FASTOR_INDEX N = get_value<2,Rest...>::value;
FASTOR_IF_CONSTEXPR(!is_boolean_expression_v<Derived>) {
for (FASTOR_INDEX i = 0; i <M; ++i) {
FASTOR_INDEX j;
for (j = 0; j <ROUND_DOWN(N,Stride_); j+=Stride_) {
src.template eval<T>(i,j).store(&_data[i*N+j], false);
}
for (; j < N; ++j) {
_data[i*N+j] = src.template eval_s<T>(i,j);
}
}
}
else {
for (FASTOR_INDEX i = 0; i <M; ++i) {
for (FASTOR_INDEX j = 0; j < N; ++j) {
_data[i*N+j] = src.template eval_s<T>(i,j);
}
}
}
}
template<typename Derived, size_t DIMS, enable_if_t_<has_tensor_view_v<Derived> && DIMS!=2 && DIMS==sizeof...(Rest) &&
requires_evaluation_v<Derived>,bool> = false>
FASTOR_INLINE Tensor(const AbstractTensor<Derived,DIMS>& src_) {
FASTOR_ASSERT(src_.self().size()==this->size(), "TENSOR SIZE MISMATCH");
assign(*this,src_.self());
}
template<typename Derived, size_t DIMS, enable_if_t_<has_tensor_view_v<Derived> && DIMS!=2 && DIMS==sizeof...(Rest) &&
!requires_evaluation_v<Derived>,bool> = false>
FASTOR_INLINE Tensor(const AbstractTensor<Derived,DIMS>& src_) {
// using scalar_type_ = typename scalar_type_finder<Derived>::type;
// constexpr FASTOR_INDEX Stride_ = simd_size_v<scalar_type_>;
const Derived &src = src_.self();
#ifndef NDEBUG
FASTOR_ASSERT(src.size()==this->size(), "TENSOR SIZE MISMATCH");
for (FASTOR_INDEX i = 0; i<sizeof...(Rest); ++i) {
FASTOR_ASSERT(src.dimension(i)==this->dimension(i), "TENSOR SHAPE MISMATCH");
}
#endif
constexpr int DimensionHolder[dimension_t::value] = {Rest...};
std::array<int,dimension_t::value> as = {};
int jt, counter=0;
while(counter < size())
{
_data[counter] = src.template teval_s<T>(as);
counter++;
for(jt = dimension_t::value-1; jt>=0; jt--)
{
as[jt] +=1;
if(as[jt]<DimensionHolder[jt])
break;
else
as[jt]=0;
}
if(jt<0)
break;
}
// // Generic vectorised version that takes care of the remainder scalar ops
// using V=SIMDVector<T,simd_abi_type>;
// while(counter < size())
// {
// const FASTOR_INDEX remainder = DimensionHolder[dimension_t::value-1] - as[dimension_t::value-1];
// if (remainder > V::Size) {
// // V _vec = src.template eval<T>(counter);
// V _vec = src.template teval<T>(as);
// _vec.store(&_data[counter],false);
// counter+=V::Size;
// }
// else {
// // _data[counter] = src.template eval_s<T>(counter);
// _data[counter] = src.template teval_s<T>(as);
// counter++;
// }
// for(jt = dimension_t::value-1; jt>=0; jt--)
// {
// if (jt == dimension_t::value-1 && remainder > V::Size) as[jt]+=V::Size;
// else as[jt] +=1;
// if(as[jt]<DimensionHolder[jt])
// break;
// else
// as[jt]=0;
// }
// if(jt<0)
// break;
// }
}
#endif // FASTOR_DISABLE_SPECIALISED_CTR
//----------------------------------------------------------------------------------------------------------//
#endif // SPECIALISED_CONSTRUCTORS_H