libpnicore
mdarray.hpp
1 //
2 // (c) Copyright 2013 DESY, Eugen Wintersberger <eugen.wintersberger@desy.de>
3 //
4 // This file is part of libpnicore.
5 //
6 // libpnicore is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 2 of the License, or
9 // (at your option) any later version.
10 //
11 // libpnicore is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with libpnicore. If not, see <http://www.gnu.org/licenses/>.
18 //
19 // ============================================================================
20 //
21 // Created on: Oct 28, 2013
22 // Author: Eugen Wintersberger <eugen.wintersberger@desy.de>
23 //
24 
25 #pragma once
26 
27 //#include<memory>
28 #include<iostream>
29 #include<sstream>
30 #include<stdexcept>
31 #include<utility>
32 #include<complex>
33 #include<cstdarg>
34 #include<cstdio>
35 #include<memory>
36 
37 
38 #include "../error/exception_utils.hpp"
39 #include "../types/types.hpp"
40 #include "../utilities.hpp"
41 #include "slice.hpp"
42 #include "array_view.hpp"
43 #include "array_factory.hpp"
44 #include "array_view_utils.hpp"
45 #include "index_map/index_maps.hpp"
46 #include "../algorithms.hpp"
47 
48 
49 namespace pni {
50 namespace core {
51 
52 
61  template<
62  typename STORAGE,
63  typename IMAP=dynamic_cindex_map,
64  typename IPA =inplace_arithmetics
65  >
66  class mdarray
67  {
68  public:
69  //================public types=====================================
71  typedef STORAGE storage_type;
73  typedef typename storage_type::value_type value_type;
75  typedef IMAP map_type;
79  typedef typename storage_type::iterator iterator;
81  typedef typename storage_type::const_iterator const_iterator;
83  typedef typename storage_type::reverse_iterator reverse_iterator;
85  typedef typename storage_type::const_reverse_iterator
88  typedef IPA inplace_arithmetic;
94  typedef size_t size_type;
95 
96 
97  //==================public members=================================
99  static const type_id_t type_id;
100  private:
102  IMAP _imap;
104  STORAGE _data;
105  public:
106 
107  //=================constructors and destructor=====================
109  mdarray():_imap(),_data() {}
110 
111  //-----------------------------------------------------------------
119  explicit mdarray(const map_type &map,const storage_type &s):
120  _imap(map),
121  _data(s)
122  {}
123 
124  //-----------------------------------------------------------------
134  explicit mdarray(map_type &&map,storage_type &&s):
135  _imap(std::move(map)),
136  _data(std::move(s))
137  {}
138 
139  //-----------------------------------------------------------------
150  template<typename ATYPE>
151  explicit mdarray(const array_view<ATYPE> &view):
152  _imap(map_utils<map_type>::create(view.template shape<shape_t>())),
153  _data(container_utils<storage_type>::create(view.size()))
154  {
155  std::copy(view.begin(),view.end(),_data.begin());
156  }
157 
158 
159  //-----------------------------------------------------------------
170  template<typename ...MDARGS>
171  explicit mdarray(const mdarray<MDARGS...> &array):
172  _imap(map_utils<map_type>::create(array.template shape<shape_t>())),
173  _data(container_utils<storage_type>::create(array.size()))
174  {
175  //copy data
176  for(size_t i=0;i<array.size();++i) (*this)[i] = array[i];
177  //std::copy(array.begin(),array.end(),this->begin());
178  }
179 
180  //====================static methods to create arrays==============
191  template<typename ...ARGS>
192  static array_type create(ARGS... arguments)
193  {
194  typedef array_factory<array_type> factory_type;
195 
196  return factory_type::create(std::forward<ARGS>(arguments)...);
197  }
198 
199  //-----------------------------------------------------------------
212  template<
213  typename T1,
214  typename T2
215  >
216  static array_type create(const std::initializer_list<T1> &l1,
217  const std::initializer_list<T2> &l2)
218  {
219  typedef array_factory<array_type> factory_type;
220 
221  return factory_type::create(l1,l2);
222  }
223 
224 
225 
226  //====================assignment operations========================
238  template<typename ...MDARGS>
239  array_type &operator=(const mdarray<MDARGS...> &array)
240  {
241  if((void*)this == (void*)&array) return *this;
242 
243  size_t s = array.size();
244  for(size_t i=0;i<s;++i) (*this)[i] = array[i];
245 
246  return *this;
247  }
248 
249  //-----------------------------------------------------------------
262  array_type &operator=(const std::initializer_list<value_type> &l)
263  {
264  if(l.size() != this->size())
266  "Size of array and initializer list do not match");
267 
268  std::copy(l.begin(),l.end(),this->begin());
269  return *this;
270  }
271 
272 
273  //================public methods===================================
280  const map_type &map() const { return this->_imap; }
281 
282  //----------------------------------------------------------------
292  template<typename CTYPE> CTYPE shape() const
293  {
294  auto c = container_utils<CTYPE>::create(_imap.rank());
295  std::copy(_imap.begin(),_imap.end(),c.begin());
296  return c;
297  }
298 
299  //-----------------------------------------------------------------
306  size_t size() const
307  {
308  return _data.size();
309  }
310 
311  //-----------------------------------------------------------------
319  size_t rank() const
320  {
321  return _imap.rank();
322  }
323 
324  //=============operators and methods to access array data==========
334  value_type& operator[](size_t i)
335  {
336 #ifdef DEBUG
337  return at(i);
338 #else
339  return _data[i];
340 #endif
341  }
342 
343  //-----------------------------------------------------------------
353  value_type operator[](size_t i) const
354  {
355 #ifdef DEBUG
356  return at(i);
357 #else
358  return _data[i];
359 #endif
360  }
361 
362  //-----------------------------------------------------------------
373  value_type &at(size_t i)
374  {
375  try
376  {
377  return _data.at(i);
378  }
379  catch(std::out_of_range &error)
380  {
381  std::stringstream ss;
382  ss<<"Index "<<i<<" is out of range ("<<size()<<")!";
383  throw index_error(EXCEPTION_RECORD,ss.str());
384  }
385 
386  }
387 
388  //-----------------------------------------------------------------
398  value_type at(size_t i) const
399  {
400  try
401  {
402  return _data.at(i);
403  }
404  catch(std::out_of_range &error)
405  {
406  std::stringstream ss;
407  ss<<"Index "<<i<<" is out of range ("<<size()<<")!";
408  throw index_error(EXCEPTION_RECORD,ss.str());
409  }
410 
411  }
412 
413  //-----------------------------------------------------------------
423  void insert(size_t i,const value_type &value)
424  {
425  at(i)=value;
426  }
427  //-----------------------------------------------------------------
440  template<
441  typename CTYPE,
442  typename = typename enable_element_cont<CTYPE>::type
443  >
444  value_type &operator()(const CTYPE &index)
445  {
446  return _data[_imap.offset(index)];
447  }
448 
449  //-----------------------------------------------------------------
462  template<
463  typename CTYPE,
464  typename = typename enable_element_cont<CTYPE>::type
465  >
466  value_type operator()(const CTYPE &index) const
467  {
468  return _data[_imap.offset(index)];
469  }
470 
471  //-----------------------------------------------------------------
482  template<
483  typename CTYPE,
484  typename = typename enable_view_cont<CTYPE>::type
485  >
487  operator()(const CTYPE &slices) const
488  {
490 
491  return view_type(*this,array_selection::create(slices));
492 
493  }
494 
495  //-----------------------------------------------------------------
506  template<
507  typename CTYPE,
508  typename = typename enable_view_cont<CTYPE>::type
509  >
511  operator()(const CTYPE &slices)
512  {
514 
515  return view_type(*this, array_selection::create(slices));
516 
517  }
518 
519  //-----------------------------------------------------------------
534  template<
535  typename... ITYPES,
536  typename = typename enable_valid_index<ITYPES...>::type
537  >
538  typename view_type_trait<array_type,ITYPES...>::type
539  operator()(ITYPES... indexes)
540  {
541  typedef view_provider<array_type,is_view_index<ITYPES...>::value>
542  provider_type;
543  return provider_type::get_reference(*this,_imap,indexes...);
544  }
545 
546 
547  //-----------------------------------------------------------------
562  template<
563  typename... ITYPES,
564  typename = typename enable_valid_index<ITYPES...>::type
565  >
566  typename view_type_trait<const array_type,ITYPES...>::const_type
567  operator()(ITYPES ...indexes) const
568  {
569  typedef view_provider<array_type,is_view_index<ITYPES...>::value>
570  provider_type;
571  return provider_type::get_value(*this,_imap,indexes...);
572  }
573 
574 
575 
576  //-----------------------------------------------------------------
584  const value_type *data() const
585  {
586  return _data.data();
587  }
588 
589  //-----------------------------------------------------------------
597  value_type *data()
598  {
599  return _data.data();
600  }
601 
602  //-----------------------------------------------------------------
611  value_type &front() { return _data.front(); }
612 
613  //-----------------------------------------------------------------
622  value_type front() const { return _data.front(); }
623 
624  //-----------------------------------------------------------------
633  value_type &back() { return _data.back(); }
634 
635  //-----------------------------------------------------------------
644  value_type back() const { return _data.back(); }
645 
646  //-----------------------------------------------------------------
653  iterator begin() { return _data.begin(); }
654 
655  //-----------------------------------------------------------------
663  iterator end() { return _data.end(); }
664 
665  //-----------------------------------------------------------------
672  const_iterator begin() const { return _data.begin(); }
673 
674  //-----------------------------------------------------------------
682  const_iterator end() const { return _data.end(); }
683 
684  //-----------------------------------------------------------------
688  reverse_iterator rbegin() { return _data.rbegin(); }
689 
690  //-----------------------------------------------------------------
694  const_reverse_iterator rbegin() const { return _data.rbegin(); }
695 
696  //-----------------------------------------------------------------
700  reverse_iterator rend() { return this->_data.rend(); }
701 
702  //-----------------------------------------------------------------
706  const_reverse_iterator rend() const { return _data.rend(); }
707 
708  //==========implementation of unary arithmetic operators===========
711 
719  array_type &operator+=(value_type s)
723  {
724  IPA::add(*this,s);
725  return *this;
726  }
727 
728  //-----------------------------------------------------------------
731 
739  template<typename ATYPE>
744  array_type &operator+=(const ATYPE &v)
745  {
746  IPA::add(*this,v);
747  return *this;
748  }
749 
750  //-----------------------------------------------------------------
753 
761  array_type &operator-=(value_type s)
765  {
766  IPA::sub(*this,s);
767  return *this;
768  }
769 
770  //-----------------------------------------------------------------
773 
781  template<typename ATYPE>
786  array_type &operator-=(const ATYPE &v)
787  {
788  IPA::sub(*this,v);
789  return *this;
790  }
791 
792  //-----------------------------------------------------------------
795 
803  array_type &operator*=(value_type s)
807  {
808  IPA::mult(*this,s);
809  return *this;
810  }
811 
812  //-----------------------------------------------------------------
815 
823  template<typename ATYPE>
828  array_type &operator*=(const ATYPE &v)
829  {
830  IPA::mult(*this,v);
831  return *this;
832  }
833 
834  //-----------------------------------------------------------------
837 
845  array_type &operator/=(value_type s)
849  {
850  IPA::div(*this,s);
851  return *this;
852  }
853 
854  //-----------------------------------------------------------------
857 
865  template<typename ATYPE>
870  array_type &operator/=(const ATYPE &v)
871  {
872  IPA::div(*this,v);
873  return *this;
874  }
875 
876 
877  };
878 
879  //-------------------------------------------------------------------------
890  template<
891  typename STORAGE,
892  typename IMAP,
893  typename IPA
894  >
895  struct container_trait<mdarray<STORAGE,IMAP,IPA>>
896  {
898  static const bool is_random_access = true;
900  static const bool is_iterable = true;
903  static const bool is_contiguous =
906  static const bool is_multidim = true;
907  };
908 
909  //set data for static member attribute
910  template<typename STORAGE,typename IMAP,typename IPA>
913  //=====================non-member operators================================
914 
924  template<
925  typename STORAGE,
926  typename IMAP,
927  typename IPA
928  >
929  std::ostream &operator<<(std::ostream &o,const mdarray<STORAGE,IMAP,IPA> &a)
930  {
931  for(auto iter = a.begin();iter!=a.end();++iter)
932  o<<*iter<<" ";
933 
934  return o;
935  }
936 
937  //-------------------------------------------------------------------------
947  template<
948  typename STORAGE,
949  typename IMAP,
950  typename IPA
951  >
952  std::istream &operator>>(std::istream &is,mdarray<STORAGE,IMAP,IPA> &a)
953  {
954  for(auto iter=a.begin();iter!=a.end();++iter)
955  is>>*iter;
956 
957  return is;
958  }
959 
960  //-------------------------------------------------------------------------
973  template<
974  typename STORAGE,
975  typename IMAP,
976  typename IPA
977  >
979  const mdarray<STORAGE,IMAP,IPA> &b2)
980  {
981  return std::equal(b1.begin(),b1.end(),b2.begin());
982  }
983 
984  //-------------------------------------------------------------------------
996  template<
997  typename STORAGE,
998  typename IMAP,
999  typename IPA
1000  >
1002  const mdarray<STORAGE,IMAP,IPA> &b2)
1003  {
1004  return !(b1==b2);
1005  }
1006 
1007 
1008 }
1009 }
static container_type create(size_t n, value_type default_value=value_type())
create container of given size
Definition: container_utils.hpp:85
mdarray(const mdarray< MDARGS...> &array)
construction from an other array
Definition: mdarray.hpp:171
IPA inplace_arithmetic
inplace arithmetics type
Definition: mdarray.hpp:88
storage_type::const_iterator const_iterator
const iterator type
Definition: mdarray.hpp:81
storage_type::const_reverse_iterator const_reverse_iterator
const reverse iterator
Definition: mdarray.hpp:86
value_type & operator()(const CTYPE &index)
return element reference
Definition: mdarray.hpp:444
value_type operator[](size_t i) const
get value at i
Definition: mdarray.hpp:353
Size mismatch error.
Definition: exceptions.hpp:399
reverse_iterator rbegin()
return reverse iterator to last element
Definition: mdarray.hpp:688
mdarray(const map_type &map, const storage_type &s)
construct from map and storage
Definition: mdarray.hpp:119
value_type operator()(const CTYPE &index) const
return element value
Definition: mdarray.hpp:466
const map_type & map() const
get index map
Definition: mdarray.hpp:280
bool operator==(const mdarray< STORAGE, IMAP, IPA > &b1, const mdarray< STORAGE, IMAP, IPA > &b2)
equality comparison operator
Definition: mdarray.hpp:978
#define EXCEPTION_RECORD
macro creating an instance of ExceptionRecord
Definition: exceptions.hpp:48
type erasure array types
Definition: array.hpp:74
void insert(size_t i, const value_type &value)
insert value at index i
Definition: mdarray.hpp:423
size_t size_type
type used for size
Definition: mdarray.hpp:94
iterator end()
iterator to last element
Definition: mdarray.hpp:663
std::istream & operator>>(std::istream &is, mdarray< STORAGE, IMAP, IPA > &a)
input stream operator
Definition: mdarray.hpp:952
const_reverse_iterator rbegin() const
return const reverse iterator to last element
Definition: mdarray.hpp:694
IMAP map_type
index map type
Definition: mdarray.hpp:75
array_type & operator/=(value_type s)
unary division of a scalar
Definition: mdarray.hpp:848
STL namespace.
array_type & operator+=(value_type s)
unary addition of a scalar
Definition: mdarray.hpp:722
STORAGE storage_type
type of the buffer object
Definition: mdarray.hpp:71
static const bool is_random_access
by default false
Definition: container_trait.hpp:60
value_type at(size_t i) const
get value at i
Definition: mdarray.hpp:398
mdarray< storage_type, map_type, IPA > array_type
type of the array
Definition: mdarray.hpp:77
value_type & at(size_t i)
get value at i
Definition: mdarray.hpp:373
array_view< const array_type > operator()(const CTYPE &slices) const
return array view
Definition: mdarray.hpp:487
storage_type::value_type value_type
arrays element type
Definition: mdarray.hpp:73
mdarray()
default constructor
Definition: mdarray.hpp:109
view_type_trait< const array_type, ITYPES...>::const_type operator()(ITYPES...indexes) const
multiindex access
Definition: mdarray.hpp:567
reverse_iterator rend()
return reverse iterator to 0-1 element
Definition: mdarray.hpp:700
container utility
Definition: container_utils.hpp:59
static const bool is_contiguous
by default false
Definition: container_trait.hpp:64
utility class for index maps
Definition: index_maps.hpp:100
array_view< array_type > view_type
view type
Definition: mdarray.hpp:90
index error
Definition: exceptions.hpp:437
iterator begin()
iterator to first element
Definition: mdarray.hpp:653
Definition: array_view_utils.hpp:299
container trait
Definition: container_trait.hpp:57
view_type_trait< array_type, ITYPES...>::type operator()(ITYPES...indexes)
multiindex access
Definition: mdarray.hpp:539
Definition: add_op.hpp:29
storage_type::reverse_iterator reverse_iterator
reverse iterator
Definition: mdarray.hpp:83
view trait
Definition: array_view_utils.hpp:238
const_iterator begin() const
const-iterator to first element
Definition: mdarray.hpp:672
static array_type create(ARGS...arguments)
generic construction function
Definition: mdarray.hpp:192
mdarray(const array_view< ATYPE > &view)
constrcut from a view
Definition: mdarray.hpp:151
IMAP _imap
Index map of the array.
Definition: mdarray.hpp:102
static const bool is_multidim
by default false
Definition: container_trait.hpp:66
template for a multi-dimensional array class
Definition: mdarray.hpp:66
value_type * data()
return pointer
Definition: mdarray.hpp:597
array factory
Definition: array_factory.hpp:50
CTYPE shape() const
shape to container
Definition: mdarray.hpp:292
static const bool is_iterable
by default false
Definition: container_trait.hpp:62
map from a type to type_id
Definition: type_id_map.hpp:55
value_type & back()
reference to last element
Definition: mdarray.hpp:633
STORAGE _data
instance of STORAGE
Definition: mdarray.hpp:104
storage_type::iterator iterator
iterator type
Definition: mdarray.hpp:79
value_type & operator[](size_t i)
get referece to element i
Definition: mdarray.hpp:334
static const type_id_t type_id
type ID of the element type
Definition: mdarray.hpp:99
array_view< const array_type > const_view_type
const view type
Definition: mdarray.hpp:92
value_type & front()
reference to first element
Definition: mdarray.hpp:611
T get_value(PTR holder_ptr)
get value from holder
Definition: utils.hpp:196
array_view< array_type > operator()(const CTYPE &slices)
return array view
Definition: mdarray.hpp:511
array_type & operator-=(const ATYPE &v)
unary subtraction of an array
Definition: mdarray.hpp:786
iterator end()
iterator to last element
Definition: array_view.hpp:573
static array_type create(const std::initializer_list< T1 > &l1, const std::initializer_list< T2 > &l2)
construction from initializer list
Definition: mdarray.hpp:216
size_t size() const
get size of array
Definition: mdarray.hpp:306
const_reverse_iterator rend() const
return const reverse iterator to 0-1 element
Definition: mdarray.hpp:706
array_type & operator=(const std::initializer_list< value_type > &l)
assignment from an initializer list
Definition: mdarray.hpp:262
array_type & operator/=(const ATYPE &v)
unary division of an array
Definition: mdarray.hpp:870
value_type back() const
value of last element
Definition: mdarray.hpp:644
mdarray(map_type &&map, storage_type &&s)
move construct from map and storage
Definition: mdarray.hpp:134
array_type & operator=(const mdarray< MDARGS...> &array)
assignment from a different array type
Definition: mdarray.hpp:239
const_iterator end() const
const-iterator to last element
Definition: mdarray.hpp:682
type_id_t
type codes for PNI data types
Definition: types/types.hpp:148
array_type & operator-=(value_type s)
unary subtraction of a scalar
Definition: mdarray.hpp:764
const value_type * data() const
return const pointer
Definition: mdarray.hpp:584
type erasure for POD data
Definition: value.hpp:46
checks for view index
Definition: array_view_utils.hpp:126
size_t rank() const
get number of dimensions
Definition: mdarray.hpp:319
array_type & operator*=(value_type s)
unary multiplication of a scalar
Definition: mdarray.hpp:806
bool operator!=(const mdarray< STORAGE, IMAP, IPA > &b1, const mdarray< STORAGE, IMAP, IPA > &b2)
inequality comparison operator
Definition: mdarray.hpp:1001
array_type & operator*=(const ATYPE &v)
unary multiplication of an array
Definition: mdarray.hpp:828
value_type front() const
value of first element
Definition: mdarray.hpp:622
iterator begin()
iterator to first element
Definition: array_view.hpp:564
static array_selection create(const CTYPE &s)
static creation function
Definition: array_selection.hpp:215
provides a view on a part of an array
Definition: add_op.hpp:32
array_type & operator+=(const ATYPE &v)
unary addition of an array
Definition: mdarray.hpp:744