123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- #ifndef _SCTL_TENSOR_HPP_
- #define _SCTL_TENSOR_HPP_
- #include <sctl/common.hpp>
- #include SCTL_INCLUDE(mem_mgr.hpp)
- #include SCTL_INCLUDE(math_utils.hpp)
- #include <iostream>
- #include <iomanip>
- namespace SCTL_NAMESPACE {
- template <class ValueType, bool own_data, Long... Args> class Tensor {
- template <Long k> static constexpr Long SizeHelper() {
- return 1;
- }
- template <Long k, Long d, Long... dd> static constexpr Long SizeHelper() {
- return (k >= 0 ? d : 1) * SizeHelper<k+1, dd...>();
- }
- template <Long k> static constexpr Long DimHelper() {
- return 1;
- }
- template <Long k, Long d0, Long... dd> static constexpr Long DimHelper() {
- return k==0 ? d0 : DimHelper<k-1,dd...>();
- }
- template <typename T> static constexpr Long OrderHelper() {
- return 0;
- }
- template <typename T, Long d, Long... dd> static constexpr Long OrderHelper() {
- return 1 + OrderHelper<void, dd...>();
- }
- template <Long k, bool own_data_, Long... dd> struct RotateType {
- using Value = Tensor<ValueType,own_data_,dd...>;
- };
- template <bool own_data_, Long d, Long... dd> struct RotateType<0,own_data_,d,dd...> {
- using Value = Tensor<ValueType,own_data_,d,dd...>;
- };
- template <Long k, bool own_data_, Long d, Long... dd> struct RotateType<k,own_data_,d,dd...> {
- using Value = typename RotateType<k-1,own_data_,dd...,d>::Value;
- };
- public:
- static constexpr Long Order() {
- return OrderHelper<void, Args...>();
- }
- static constexpr Long Size() {
- return SizeHelper<0,Args...>();
- }
- template <Long k> static constexpr Long Dim() {
- return DimHelper<k,Args...>();
- }
- Tensor(Iterator<ValueType> src_iter = NullIterator<ValueType>()) {
- Init(src_iter);
- }
- Tensor(const Tensor &M) {
- Init((Iterator<ValueType>)M.begin());
- }
- explicit Tensor(const ValueType& v) {
- static_assert(own_data || Size() == 0, "Memory pointer must be provided to initialize Tensor types with own_data=false");
- Init(NullIterator<ValueType>());
- for (auto& x : *this) x = v;
- }
- template <bool own_data_> Tensor(const Tensor<ValueType,own_data_,Args...> &M) {
- static_assert(Size() <= M.Size(), "Initializer must be at least the size of the object.");
- Init((Iterator<ValueType>)M.begin());
- }
- Tensor &operator=(const Tensor &M) {
- memcopy(begin(), M.begin(), Size());
- return *this;
- }
- Tensor &operator=(const ValueType& v) {
- for (auto& x : *this) x = v;
- return *this;
- }
- Iterator<ValueType> begin() {
- return own_data ? (Iterator<ValueType>)buff : iter_[0];
- }
- ConstIterator<ValueType> begin() const {
- return own_data ? (ConstIterator<ValueType>)buff : (ConstIterator<ValueType>)iter_[0];
- }
- Iterator<ValueType> end() {
- return begin() + Size();
- }
- ConstIterator<ValueType> end() const {
- return begin() + Size();
- }
- template <class ...PackedLong> ValueType& operator()(PackedLong... ii) {
- return begin()[offset<0>(ii...)];
- }
- template <class ...PackedLong> ValueType operator()(PackedLong... ii) const {
- return begin()[offset<0>(ii...)];
- }
- typename RotateType<1,true,Args...>::Value RotateLeft() const {
- typename RotateType<1,true,Args...>::Value Tr;
- const auto& T = *this;
- constexpr Long N0 = Dim<0>();
- constexpr Long N1 = Size() / N0;
- for (Long i = 0; i < N0; i++) {
- for (Long j = 0; j < N1; j++) {
- Tr.begin()[j*N0+i] = T.begin()[i*N1+j];
- }
- }
- return Tr;
- }
- typename RotateType<Order()-1,true,Args...>::Value RotateRight() const {
- typename RotateType<Order()-1,true,Args...>::Value Tr;
- const auto& T = *this;
- constexpr Long N0 = Dim<Order()-1>();
- constexpr Long N1 = Size() / N0;
- for (Long i = 0; i < N0; i++) {
- for (Long j = 0; j < N1; j++) {
- Tr.begin()[i*N1+j] = T.begin()[j*N0+i];
- }
- }
- return Tr;
- }
- Tensor<ValueType, true, Args...> operator-() const {
- Tensor<ValueType, true, Args...> M0;
- const auto &M1 = *this;
- for (Long i = 0; i < Size(); i++) {
- M0.begin()[i] = -M1.begin()[i];
- }
- return M0;
- }
- Tensor<ValueType, true, Args...> operator*(const ValueType &s) const {
- Tensor<ValueType, true, Args...> M0;
- const auto &M1 = *this;
- for (Long i = 0; i < Size(); i++) {
- M0.begin()[i] = M1.begin()[i]*s;
- }
- return M0;
- }
- Tensor<ValueType, true, Args...> operator/(const ValueType &s) const {
- Tensor<ValueType, true, Args...> M0;
- const auto &M1 = *this;
- for (Long i = 0; i < Size(); i++) {
- M0.begin()[i] = M1.begin()[i]/s;
- }
- return M0;
- }
- template <bool own_data_> Tensor<ValueType, true, Args...> operator+(const Tensor<ValueType, own_data_, Args...> &M2) const {
- Tensor<ValueType, true, Args...> M0;
- const auto &M1 = *this;
- for (Long i = 0; i < Size(); i++) {
- M0.begin()[i] = M1.begin()[i] + M2.begin()[i];
- }
- return M0;
- }
- template <bool own_data_> Tensor<ValueType, true, Args...> operator-(const Tensor<ValueType, own_data_, Args...> &M2) const {
- Tensor<ValueType, true, Args...> M0;
- const auto &M1 = *this;
- for (Long i = 0; i < Size(); i++) {
- M0.begin()[i] = M1.begin()[i] - M2.begin()[i];
- }
- return M0;
- }
- template <bool own_data_, Long N1, Long N2> Tensor<ValueType, true, Dim<0>(), N2> operator*(const Tensor<ValueType, own_data_, N1, N2> &M2) const {
- static_assert(Order() == 2, "Multiplication is only defined for tensors of order two.");
- static_assert(Dim<1>() == N1, "Tensor dimensions dont match for multiplication.");
- Tensor<ValueType, true, Dim<0>(), N2> M0;
- const auto &M1 = *this;
- for (Long i = 0; i < Dim<0>(); i++) {
- for (Long j = 0; j < N2; j++) {
- ValueType Mij = 0;
- for (Long k = 0; k < N1; k++) {
- Mij += M1(i,k)*M2(k,j);
- }
- M0(i,j) = Mij;
- }
- }
- return M0;
- }
- private:
- template <Integer k> static Long offset() {
- return 0;
- }
- template <Integer k, class ...PackedLong> static Long offset(Long i, PackedLong... ii) {
- return i * SizeHelper<-(k+1),Args...>() + offset<k+1>(ii...);
- }
- void Init(Iterator<ValueType> src_iter) {
- if (own_data) {
- if (src_iter != NullIterator<ValueType>()) {
- memcopy((Iterator<ValueType>)buff, src_iter, Size());
- }
- } else {
- if (Size()) {
- SCTL_UNUSED(src_iter[0]);
- SCTL_UNUSED(src_iter[Size()-1]);
- iter_[0] = Ptr2Itr<ValueType>(&src_iter[0], Size());
- } else {
- iter_[0] = NullIterator<ValueType>();
- }
- }
- }
- StaticArray<ValueType,own_data?Size():0> buff;
- StaticArray<Iterator<ValueType>,own_data?0:1> iter_;
- };
- template <class ValueType, bool own_data, Long N1, Long N2> std::ostream& operator<<(std::ostream &output, const Tensor<ValueType, own_data, N1, N2> &M) {
- std::ios::fmtflags f(std::cout.flags());
- output << std::fixed << std::setprecision(4) << std::setiosflags(std::ios::left);
- for (Long i = 0; i < N1; i++) {
- for (Long j = 0; j < N2; j++) {
- float f = ((float)M(i,j));
- if (sctl::fabs<float>(f) < 1e-25) f = 0;
- output << std::setw(10) << ((double)f) << ' ';
- }
- output << ";\n";
- }
- std::cout.flags(f);
- return output;
- }
- } // end namespace
- #endif //_SCTL_TENSOR_HPP_
|