Alexandria  2.22.0
Please provide a description of the project.
NdArray.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012-2021 Euclid Science Ground Segment
3  *
4  * This library is free software; you can redistribute it and/or modify it under
5  * the terms of the GNU Lesser General Public License as published by the Free
6  * Software Foundation; either version 3.0 of the License, or (at your option)
7  * any later version.
8  *
9  * This library is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12  * details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
25 #ifndef ALEXANDRIA_NDARRAY_H
26 #define ALEXANDRIA_NDARRAY_H
27 
29 #include <cassert>
30 #include <iostream>
31 #include <numeric>
32 #include <stdexcept>
33 #include <vector>
34 
35 namespace Euclid {
36 namespace NdArray {
37 
45 template <typename T>
46 class NdArray {
47 private:
48  struct ContainerInterface;
49 
50  template <template <class...> class Container = std::vector>
51  struct ContainerWrapper;
52 
53 public:
55 
61  template <bool Const>
62  class Iterator
63  : public std::iterator<std::random_access_iterator_tag, typename std::conditional<Const, const T, T>::type> {
64  private:
67  size_t m_i;
68 
69  Iterator(ContainerInterface* container_ptr, size_t offset, const std::vector<size_t>& shape,
70  const std::vector<size_t>& strides, size_t start);
71 
72  Iterator(ContainerInterface* container_ptr, size_t offset, size_t row_size, size_t stride, size_t start);
73 
74  friend class NdArray;
75 
76  public:
81 
85  Iterator(const Iterator<false>& other); // cppcheck-suppress noExplicitConstructor
86 
91 
96 
100  bool operator==(const Iterator& other) const;
101 
105  bool operator!=(const Iterator& other) const;
106 
113 
120 
126  Iterator& operator+=(size_t n);
127 
133  Iterator operator+(size_t n);
134 
141  Iterator& operator-=(size_t n);
142 
149  Iterator operator-(size_t n);
150 
156  difference_type operator-(const Iterator& other);
157 
161  value_t& operator[](size_t i);
162 
166  value_t operator[](size_t i) const;
167 
173  bool operator<(const Iterator& other);
174 
180  bool operator>(const Iterator& other);
181  };
182 
185 
189  virtual ~NdArray() = default;
190 
197  explicit NdArray(const std::vector<size_t>& shape_);
198 
209  template <template <class...> class Container = std::vector>
210  NdArray(const std::vector<size_t>& shape_, const Container<T>& data);
211 
226  template <template <class...> class Container = std::vector>
227  NdArray(const std::vector<size_t>& shape_, Container<T>&& data);
228 
241  template <typename Iterator>
243 
254  template <typename... Args>
255  NdArray(const std::vector<size_t>& shape_, const std::vector<std::string>& attr_names, Args&&... args);
256 
263  explicit NdArray(const std::initializer_list<size_t>& shape_) : NdArray(std::vector<size_t>{shape_}) {}
264 
270  NdArray(const self_type&) = default;
271 
275  NdArray(self_type&&) = default;
276 
282  NdArray& operator=(const NdArray&) = default;
283 
287  NdArray copy() const {
288  return self_type{this};
289  }
290 
296  const std::vector<size_t> shape() const {
297  return m_shape;
298  }
299 
313 
324  template <typename... D>
325  self_type& reshape(size_t i, D... rest);
326 
334  T& at(const std::vector<size_t>& coords);
335 
343  const T& at(const std::vector<size_t>& coords) const;
344 
354  T& at(const std::vector<size_t>& coords, const std::string& attr);
355 
365  const T& at(const std::vector<size_t>& coords, const std::string& attr) const;
366 
377  template <typename... D>
378  T& at(size_t i, D... rest);
379 
390  template <typename... D>
391  const T& at(size_t i, D... rest) const;
392 
398 
404 
410 
416 
420  size_t size() const;
421 
425  bool operator==(const self_type& b) const;
426 
430  bool operator!=(const self_type& b) const;
431 
437 
441  self_type slice(size_t i);
442 
446  const self_type slice(size_t i) const;
447 
451  self_type rslice(size_t i);
452 
456  const self_type rslice(size_t i) const;
457 
463 
464 private:
465  size_t m_offset;
468  size_t m_size;
469 
474 
475  virtual ~ContainerInterface() = default;
476 
478  T at(size_t offset) const {
479  return m_data_ptr[offset];
480  }
481 
483  T& at(size_t offset) {
484  return m_data_ptr[offset];
485  }
486 
488  virtual size_t size() const = 0;
489 
491  virtual void resize(const std::vector<size_t>& shape) = 0;
492 
495  };
496 
497  template <template <class...> class Container>
500  Container<T> m_container;
501 
502  ~ContainerWrapper() = default;
503 
505 
507 
508  template <typename... Args>
509  explicit ContainerWrapper(Args&&... args) : m_container(std::forward<Args>(args)...) {
510  m_data_ptr = m_container.data();
511  }
512 
513  size_t size() const final {
514  return m_container.size();
515  }
516 
517  template <typename T2>
519  -> decltype((void)std::declval<Container<T2>>().resize(std::vector<size_t>{}), void()) {
520  m_container.resize(shape);
521  }
522 
523  template <typename T2>
525  -> decltype((void)std::declval<Container<T2>>().resize(size_t{}), void()) {
526  auto new_size = std::accumulate(shape.begin(), shape.end(), 1u, std::multiplies<size_t>());
527  m_container.resize(new_size);
528  }
529 
537  void resize(const std::vector<size_t>& shape) final {
538  resizeImpl<T>(shape);
539  m_data_ptr = m_container.data();
540  }
541 
543  return Euclid::make_unique<ContainerWrapper>(m_container);
544  }
545  };
546 
548 
552  explicit NdArray(const self_type* other);
553 
558  const std::vector<size_t>& stride, const std::vector<std::string>& attr_names);
559 
565  size_t get_offset(const std::vector<size_t>& coords) const;
566 
572  size_t get_attr_offset(const std::string& attr) const;
573 
578 
582  template <typename... D>
583  T& at_helper(size_t offset_acc, size_t axis, size_t i, D... rest);
584 
588  T& at_helper(size_t offset_acc, size_t axis);
589 
593  T& at_helper(size_t offset_acc, size_t axis, const std::string& attr);
594 
598  template <typename... D>
599  const T& at_helper(size_t offset_acc, size_t axis, size_t i, D... rest) const;
600 
604  const T& at_helper(size_t offset_acc, size_t axis) const;
605 
609  const T& at_helper(size_t offset_acc, size_t axis, const std::string& attr) const;
610 
611  template <typename... D>
612  self_type& reshape_helper(std::vector<size_t>& acc, size_t i, D... rest);
613 
615 };
616 
620 template <typename T>
622 
623 } // namespace NdArray
624 } // namespace Euclid
625 
626 #define NDARRAY_IMPL
628 #undef NDARRAY_IMPL
629 
630 #endif // ALEXANDRIA_NDARRAY_H
T accumulate(T... args)
T begin(T... args)
Iterator(ContainerInterface *container_ptr, size_t offset, size_t row_size, size_t stride, size_t start)
Iterator & operator+=(size_t n)
bool operator!=(const Iterator &other) const
typename std::conditional< Const, const T, T >::type value_t
Definition: NdArray.h:77
Iterator & operator-=(size_t n)
bool operator>(const Iterator &other)
bool operator<(const Iterator &other)
Iterator(ContainerInterface *container_ptr, size_t offset, const std::vector< size_t > &shape, const std::vector< size_t > &strides, size_t start)
ContainerInterface * m_container_ptr
Definition: NdArray.h:65
bool operator==(const Iterator &other) const
Iterator(const Iterator< false > &other)
value_t operator[](size_t i) const
difference_type operator-(const Iterator &other)
NdArray(const std::vector< size_t > &shape_, Container< T > &&data)
const T & at_helper(size_t offset_acc, size_t axis, const std::string &attr) const
std::vector< std::string > m_attr_names
Definition: NdArray.h:467
size_t get_offset(const std::vector< size_t > &coords) const
self_type & reshape(size_t i, D... rest)
NdArray(const std::vector< size_t > &shape_)
NdArray(std::shared_ptr< ContainerInterface > container, size_t offset, const std::vector< size_t > &shape, const std::vector< size_t > &stride, const std::vector< std::string > &attr_names)
T & at(const std::vector< size_t > &coords, const std::string &attr)
T & at_helper(size_t offset_acc, size_t axis, const std::string &attr)
NdArray(const std::vector< size_t > &shape_, const std::vector< std::string > &attr_names, Args &&... args)
NdArray(const self_type *other)
self_type slice(size_t i)
Iterator< true > const_iterator
Definition: NdArray.h:183
T & at(const std::vector< size_t > &coords)
const T & at(size_t i, D... rest) const
bool operator!=(const self_type &b) const
self_type & reshape_helper(std::vector< size_t > &acc)
T & at(size_t i, D... rest)
T & at_helper(size_t offset_acc, size_t axis, size_t i, D... rest)
self_type rslice(size_t i)
const std::vector< size_t > shape() const
Definition: NdArray.h:296
NdArray & operator=(const NdArray &)=default
std::shared_ptr< ContainerInterface > m_container
Definition: NdArray.h:547
NdArray copy() const
Definition: NdArray.h:287
std::vector< size_t > m_shape
Definition: NdArray.h:466
NdArray(const std::initializer_list< size_t > &shape_)
Definition: NdArray.h:263
NdArray(const std::vector< size_t > &shape_, const Container< T > &data)
const_iterator begin() const
std::vector< size_t > m_stride_size
Definition: NdArray.h:466
const T & at(const std::vector< size_t > &coords, const std::string &attr) const
NdArray(const self_type &)=default
T & at_helper(size_t offset_acc, size_t axis)
const T & at(const std::vector< size_t > &coords) const
const self_type rslice(size_t i) const
size_t get_attr_offset(const std::string &attr) const
const std::vector< std::string > & attributes() const
NdArray(self_type &&)=default
self_type & reshape_helper(std::vector< size_t > &acc, size_t i, D... rest)
Iterator< false > iterator
Definition: NdArray.h:184
const T & at_helper(size_t offset_acc, size_t axis) const
NdArray(const std::vector< size_t > &shape_, Iterator begin, Iterator end)
bool operator==(const self_type &b) const
const T & at_helper(size_t offset_acc, size_t axis, size_t i, D... rest) const
self_type & reshape(const std::vector< size_t > &new_shape)
const_iterator end() const
virtual ~NdArray()=default
const self_type slice(size_t i) const
self_type & concatenate(const self_type &other)
NdArray< T > self_type
Definition: NdArray.h:51
T declval(T... args)
T end(T... args)
std::ostream & operator<<(std::ostream &out, const NdArray< T > &ndarray)
STL namespace.
virtual std::unique_ptr< ContainerInterface > copy() const =0
Expected to generate a deep copy of the underlying data.
virtual void resize(const std::vector< size_t > &shape)=0
Resize container.
std::unique_ptr< ContainerInterface > copy() const final
Expected to generate a deep copy of the underlying data.
Definition: NdArray.h:542
ContainerWrapper(const ContainerWrapper &)=delete
auto resizeImpl(const std::vector< size_t > &shape) -> decltype((void) std::declval< Container< T2 >>().resize(size_t{}), void())
Definition: NdArray.h:524
void resize(const std::vector< size_t > &shape) final
Definition: NdArray.h:537
ContainerWrapper(ContainerWrapper &&)=default
auto resizeImpl(const std::vector< size_t > &shape) -> decltype((void) std::declval< Container< T2 >>().resize(std::vector< size_t >{}), void())
Definition: NdArray.h:518