File indexing completed on 2025-01-18 09:43:03
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef BOOST_UBLAS_TENSOR_IMPL_HPP
0017 #define BOOST_UBLAS_TENSOR_IMPL_HPP
0018
0019 #include <boost/config.hpp>
0020
0021 #include <initializer_list>
0022
0023 #include "algorithms.hpp"
0024 #include "expression.hpp"
0025 #include "expression_evaluation.hpp"
0026 #include "extents.hpp"
0027 #include "strides.hpp"
0028 #include "index.hpp"
0029
0030 namespace boost { namespace numeric { namespace ublas {
0031
0032 template<class T, class F, class A>
0033 class tensor;
0034
0035 template<class T, class F, class A>
0036 class matrix;
0037
0038 template<class T, class A>
0039 class vector;
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078 template<class T, class F = first_order, class A = std::vector<T,std::allocator<T>> >
0079 class tensor:
0080 public detail::tensor_expression<tensor<T, F, A>,tensor<T, F, A>>
0081 {
0082
0083 static_assert( std::is_same<F,first_order>::value ||
0084 std::is_same<F,last_order >::value, "boost::numeric::tensor template class only supports first- or last-order storage formats.");
0085
0086 using self_type = tensor<T, F, A>;
0087 public:
0088
0089
0090
0091 template<class derived_type>
0092 using tensor_expression_type = detail::tensor_expression<self_type,derived_type>;
0093
0094 template<class derived_type>
0095 using matrix_expression_type = matrix_expression<derived_type>;
0096
0097 template<class derived_type>
0098 using vector_expression_type = vector_expression<derived_type>;
0099
0100 using super_type = tensor_expression_type<self_type>;
0101
0102
0103
0104 using array_type = A;
0105 using layout_type = F;
0106
0107
0108 using size_type = typename array_type::size_type;
0109 using difference_type = typename array_type::difference_type;
0110 using value_type = typename array_type::value_type;
0111
0112 using reference = typename array_type::reference;
0113 using const_reference = typename array_type::const_reference;
0114
0115 using pointer = typename array_type::pointer;
0116 using const_pointer = typename array_type::const_pointer;
0117
0118 using iterator = typename array_type::iterator;
0119 using const_iterator = typename array_type::const_iterator;
0120
0121 using reverse_iterator = typename array_type::reverse_iterator;
0122 using const_reverse_iterator = typename array_type::const_reverse_iterator;
0123
0124 using tensor_temporary_type = self_type;
0125 using storage_category = dense_tag;
0126
0127 using strides_type = basic_strides<std::size_t,layout_type>;
0128 using extents_type = shape;
0129
0130 using matrix_type = matrix<value_type,layout_type,array_type>;
0131 using vector_type = vector<value_type,array_type>;
0132
0133
0134
0135
0136
0137
0138
0139
0140 BOOST_UBLAS_INLINE
0141 constexpr tensor ()
0142 : tensor_expression_type<self_type>()
0143 , extents_()
0144 , strides_()
0145 , data_()
0146 {
0147 }
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158 explicit BOOST_UBLAS_INLINE
0159 tensor (std::initializer_list<size_type> l)
0160 : tensor_expression_type<self_type>()
0161 , extents_ (std::move(l))
0162 , strides_ (extents_)
0163 , data_ (extents_.product())
0164 {
0165 }
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176 explicit BOOST_UBLAS_INLINE
0177 tensor (extents_type const& s)
0178 : tensor_expression_type<self_type>()
0179 , extents_ (s)
0180 , strides_ (extents_)
0181 , data_ (extents_.product())
0182 {}
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193 BOOST_UBLAS_INLINE
0194 tensor (extents_type const& s, const array_type &a)
0195 : tensor_expression_type<self_type>()
0196 , extents_ (s)
0197 , strides_ (extents_)
0198 , data_ (a)
0199 {
0200 if(this->extents_.product() != this->data_.size())
0201 throw std::runtime_error("Error in boost::numeric::ublas::tensor: size of provided data and specified extents do not match.");
0202 }
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213 BOOST_UBLAS_INLINE
0214 tensor (extents_type const& e, const value_type &i)
0215 : tensor_expression_type<self_type>()
0216 , extents_ (e)
0217 , strides_ (extents_)
0218 , data_ (extents_.product(), i)
0219 {}
0220
0221
0222
0223
0224
0225
0226
0227 BOOST_UBLAS_INLINE
0228 tensor (const tensor &v)
0229 : tensor_expression_type<self_type>()
0230 , extents_ (v.extents_)
0231 , strides_ (v.strides_)
0232 , data_ (v.data_ )
0233 {}
0234
0235
0236
0237
0238
0239
0240
0241 BOOST_UBLAS_INLINE
0242 tensor (tensor &&v)
0243 : tensor_expression_type<self_type>()
0244 , extents_ (std::move(v.extents_))
0245 , strides_ (std::move(v.strides_))
0246 , data_ (std::move(v.data_ ))
0247 {}
0248
0249
0250
0251
0252
0253
0254
0255
0256 BOOST_UBLAS_INLINE
0257 tensor (const matrix_type &v)
0258 : tensor_expression_type<self_type>()
0259 , extents_ ()
0260 , strides_ ()
0261 , data_ (v.data())
0262 {
0263 if(!data_.empty()){
0264 extents_ = extents_type{v.size1(),v.size2()};
0265 strides_ = strides_type(extents_);
0266 }
0267 }
0268
0269
0270
0271
0272
0273
0274
0275 BOOST_UBLAS_INLINE
0276 tensor (matrix_type &&v)
0277 : tensor_expression_type<self_type>()
0278 , extents_ {}
0279 , strides_ {}
0280 , data_ {}
0281 {
0282 if(v.size1()*v.size2() != 0){
0283 extents_ = extents_type{v.size1(),v.size2()};
0284 strides_ = strides_type(extents_);
0285 data_ = std::move(v.data());
0286 }
0287 }
0288
0289
0290
0291
0292
0293
0294
0295
0296 BOOST_UBLAS_INLINE
0297 tensor (const vector_type &v)
0298 : tensor_expression_type<self_type>()
0299 , extents_ ()
0300 , strides_ ()
0301 , data_ (v.data())
0302 {
0303 if(!data_.empty()){
0304 extents_ = extents_type{data_.size(),1};
0305 strides_ = strides_type(extents_);
0306 }
0307 }
0308
0309
0310
0311
0312
0313 BOOST_UBLAS_INLINE
0314 tensor (vector_type &&v)
0315 : tensor_expression_type<self_type>()
0316 , extents_ {}
0317 , strides_ {}
0318 , data_ {}
0319 {
0320 if(v.size() != 0){
0321 extents_ = extents_type{v.size(),1};
0322 strides_ = strides_type(extents_);
0323 data_ = std::move(v.data());
0324 }
0325 }
0326
0327
0328
0329
0330
0331
0332 BOOST_UBLAS_INLINE
0333 template<class other_layout>
0334 tensor (const tensor<value_type, other_layout> &other)
0335 : tensor_expression_type<self_type> ()
0336 , extents_ (other.extents())
0337 , strides_ (other.extents())
0338 , data_ (other.extents().product())
0339 {
0340 copy(this->rank(), this->extents().data(),
0341 this->data(), this->strides().data(),
0342 other.data(), other.strides().data());
0343 }
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354 BOOST_UBLAS_INLINE
0355 template<class derived_type>
0356 tensor (const tensor_expression_type<derived_type> &expr)
0357 : tensor_expression_type<self_type> ()
0358 , extents_ ( detail::retrieve_extents(expr) )
0359 , strides_ ( extents_ )
0360 , data_ ( extents_.product() )
0361 {
0362 static_assert( detail::has_tensor_types<self_type, tensor_expression_type<derived_type>>::value,
0363 "Error in boost::numeric::ublas::tensor: expression does not contain a tensor. cannot retrieve shape.");
0364 detail::eval( *this, expr );
0365 }
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376 BOOST_UBLAS_INLINE
0377 template<class derived_type>
0378 tensor (const matrix_expression_type<derived_type> &expr)
0379 : tensor( matrix_type ( expr ) )
0380 {
0381 }
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392 BOOST_UBLAS_INLINE
0393 template<class derived_type>
0394 tensor (const vector_expression_type<derived_type> &expr)
0395 : tensor( vector_type ( expr ) )
0396 {
0397 }
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407 BOOST_UBLAS_INLINE
0408 template<class derived_type>
0409 tensor &operator = (const tensor_expression_type<derived_type> &expr)
0410 {
0411 detail::eval(*this, expr);
0412 return *this;
0413 }
0414
0415 tensor& operator=(tensor other)
0416 {
0417 swap (*this, other);
0418 return *this;
0419 }
0420
0421 tensor& operator=(const_reference v)
0422 {
0423 std::fill(this->begin(), this->end(), v);
0424 return *this;
0425 }
0426
0427
0428 BOOST_UBLAS_INLINE
0429 bool empty () const {
0430 return this->data_.empty();
0431 }
0432
0433
0434
0435 BOOST_UBLAS_INLINE
0436 size_type size () const {
0437 return this->data_.size ();
0438 }
0439
0440
0441 BOOST_UBLAS_INLINE
0442 size_type size (size_type r) const {
0443 return this->extents_.at(r);
0444 }
0445
0446
0447 BOOST_UBLAS_INLINE
0448 size_type rank () const {
0449 return this->extents_.size();
0450 }
0451
0452
0453 BOOST_UBLAS_INLINE
0454 size_type order () const {
0455 return this->extents_.size();
0456 }
0457
0458
0459 BOOST_UBLAS_INLINE
0460 strides_type const& strides () const {
0461 return this->strides_;
0462 }
0463
0464
0465 BOOST_UBLAS_INLINE
0466 extents_type const& extents () const {
0467 return this->extents_;
0468 }
0469
0470
0471
0472 BOOST_UBLAS_INLINE
0473 const_pointer data () const {
0474 return this->data_.data();
0475 }
0476
0477
0478 BOOST_UBLAS_INLINE
0479 pointer data () {
0480 return this->data_.data();
0481 }
0482
0483
0484
0485
0486
0487
0488
0489 BOOST_UBLAS_INLINE
0490 const_reference operator [] (size_type i) const {
0491 return this->data_[i];
0492 }
0493
0494
0495
0496
0497
0498
0499
0500
0501 BOOST_UBLAS_INLINE
0502 reference operator [] (size_type i)
0503 {
0504 return this->data_[i];
0505 }
0506
0507
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517 template<class ... size_types>
0518 BOOST_UBLAS_INLINE
0519 const_reference at (size_type i, size_types ... is) const {
0520 if constexpr (sizeof...(is) == 0)
0521 return this->data_[i];
0522 else
0523 return this->data_[detail::access<0ul>(size_type(0),this->strides_,i,std::forward<size_types>(is)...)];
0524 }
0525
0526
0527
0528
0529
0530
0531
0532
0533
0534
0535 BOOST_UBLAS_INLINE
0536 template<class ... size_types>
0537 reference at (size_type i, size_types ... is) {
0538 if constexpr (sizeof...(is) == 0)
0539 return this->data_[i];
0540 else
0541 return this->data_[detail::access<0ul>(size_type(0),this->strides_,i,std::forward<size_types>(is)...)];
0542 }
0543
0544
0545
0546
0547
0548
0549
0550
0551
0552
0553
0554 BOOST_UBLAS_INLINE
0555 const_reference operator()(size_type i) const {
0556 return this->data_[i];
0557 }
0558
0559
0560
0561
0562
0563
0564
0565
0566 BOOST_UBLAS_INLINE
0567 reference operator()(size_type i){
0568 return this->data_[i];
0569 }
0570
0571
0572
0573
0574
0575
0576
0577
0578
0579
0580
0581
0582 BOOST_UBLAS_INLINE
0583 template<std::size_t I, class ... index_types>
0584 decltype(auto) operator() (index::index_type<I> p, index_types ... ps) const
0585 {
0586 constexpr auto N = sizeof...(ps)+1;
0587 if( N != this->rank() )
0588 throw std::runtime_error("Error in boost::numeric::ublas::operator(): size of provided index_types does not match with the rank.");
0589
0590 return std::make_pair( std::cref(*this), std::make_tuple( p, std::forward<index_types>(ps)... ) );
0591 }
0592
0593
0594
0595
0596
0597
0598
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609
0610
0611 BOOST_UBLAS_INLINE
0612 void reshape (extents_type const& e, value_type v = value_type{})
0613 {
0614 this->extents_ = e;
0615 this->strides_ = strides_type(this->extents_);
0616
0617 if(e.product() != this->size())
0618 this->data_.resize (this->extents_.product(), v);
0619 }
0620
0621
0622
0623
0624
0625 friend void swap(tensor& lhs, tensor& rhs) {
0626 std::swap(lhs.data_ , rhs.data_ );
0627 std::swap(lhs.extents_, rhs.extents_);
0628 std::swap(lhs.strides_, rhs.strides_);
0629 }
0630
0631
0632
0633 BOOST_UBLAS_INLINE
0634 const_iterator begin () const {
0635 return data_.begin ();
0636 }
0637
0638
0639 BOOST_UBLAS_INLINE
0640 const_iterator cbegin () const {
0641 return data_.cbegin ();
0642 }
0643
0644
0645 BOOST_UBLAS_INLINE
0646 const_iterator end () const {
0647 return data_.end();
0648 }
0649
0650
0651 BOOST_UBLAS_INLINE
0652 const_iterator cend () const {
0653 return data_.cend ();
0654 }
0655
0656
0657 BOOST_UBLAS_INLINE
0658 iterator begin () {
0659 return data_.begin();
0660 }
0661
0662
0663 BOOST_UBLAS_INLINE
0664 iterator end () {
0665 return data_.end();
0666 }
0667
0668
0669 BOOST_UBLAS_INLINE
0670 const_reverse_iterator rbegin () const {
0671 return data_.rbegin();
0672 }
0673
0674
0675 BOOST_UBLAS_INLINE
0676 const_reverse_iterator crbegin () const {
0677 return data_.crbegin();
0678 }
0679
0680
0681 BOOST_UBLAS_INLINE
0682 const_reverse_iterator rend () const {
0683 return data_.rend();
0684 }
0685
0686
0687 BOOST_UBLAS_INLINE
0688 const_reverse_iterator crend () const {
0689 return data_.crend();
0690 }
0691
0692
0693 BOOST_UBLAS_INLINE
0694 reverse_iterator rbegin () {
0695 return data_.rbegin();
0696 }
0697
0698
0699 BOOST_UBLAS_INLINE
0700 reverse_iterator rend () {
0701 return data_.rend();
0702 }
0703
0704
0705 #if 0
0706
0707
0708
0709
0710
0711
0712
0713 template<class Archive>
0714 void serialize(Archive & ar, const unsigned int ){
0715 ar & serialization::make_nvp("data",data_);
0716 }
0717 #endif
0718
0719
0720
0721 private:
0722
0723 extents_type extents_;
0724 strides_type strides_;
0725 array_type data_;
0726 };
0727
0728 }}}
0729
0730
0731
0732
0733
0734 #endif