Alexandria  2.19
Please provide a description of the project.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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>
52 
53 public:
54  typedef NdArray<T> self_type;
55 
61  template <bool Const>
62  class Iterator : public std::iterator<std::random_access_iterator_tag, typename std::conditional<Const, const T, T>::type> {
63  private:
65  size_t m_offset;
66 
67  Iterator(ContainerInterface* container_ptr, size_t offset);
68 
69  friend class NdArray;
70 
71  public:
76 
80  Iterator(const Iterator<false>& other);
81 
86 
90  Iterator operator++(int);
91 
95  bool operator==(const Iterator& other) const;
96 
100  bool operator!=(const Iterator& other) const;
101 
107  value_t& operator*();
108 
114  value_t operator*() const;
115 
121  Iterator& operator+=(size_t n);
122 
128  Iterator operator+(size_t n);
129 
136  Iterator& operator-=(size_t n);
137 
144  Iterator operator-(size_t n);
145 
151  difference_type operator-(const Iterator& other);
152 
156  value_t& operator[](size_t i);
157 
163  bool operator<(const Iterator& other);
164 
170  bool operator>(const Iterator& other);
171  };
172 
175 
179  virtual ~NdArray() = default;
180 
187  explicit NdArray(const std::vector<size_t>& shape_);
188 
199  template <template <class...> class Container = std::vector>
200  NdArray(const std::vector<size_t>& shape_, const Container<T>& data);
201 
216  template <template <class...> class Container = std::vector>
217  NdArray(const std::vector<size_t>& shape_, Container<T>&& data);
218 
231  template <typename Iterator>
233 
244  template <typename... Args>
245  NdArray(const std::vector<size_t>& shape_, const std::vector<std::string>& attr_names, Args&&... args);
246 
253  NdArray(const std::initializer_list<size_t>& shape_) : NdArray(std::vector<size_t>{shape_}) {}
254 
260  NdArray(const self_type&) = default;
261 
265  NdArray(self_type&&) = default;
266 
272  NdArray& operator=(const NdArray&) = default;
273 
277  NdArray copy() const {
278  return self_type{this};
279  }
280 
286  const std::vector<size_t> shape() const {
287  return m_shape;
288  }
289 
302  self_type& reshape(const std::vector<size_t> new_shape);
303 
314  template <typename... D>
315  self_type& reshape(size_t i, D... rest);
316 
324  T& at(const std::vector<size_t>& coords);
325 
333  const T& at(const std::vector<size_t>& coords) const;
334 
344  T& at(const std::vector<size_t>& coords, const std::string& attr);
345 
355  const T& at(const std::vector<size_t>& coords, const std::string& attr) const;
356 
367  template <typename... D>
368  T& at(size_t i, D... rest);
369 
380  template <typename... D>
381  const T& at(size_t i, D... rest) const;
382 
387  iterator begin();
388 
393  iterator end();
394 
399  const_iterator begin() const;
400 
405  const_iterator end() const;
406 
410  size_t size() const;
411 
415  bool operator==(const self_type& b) const;
416 
420  bool operator!=(const self_type& b) const;
421 
426  self_type& concatenate(const self_type& other);
427 
432  const std::vector<std::string>& attributes() const;
433 
434 private:
437  size_t m_size;
438 
443 
444  virtual ~ContainerInterface() = default;
445 
447  T at(size_t offset) const {
448  return m_data_ptr[offset];
449  }
450 
452  T& at(size_t offset) {
453  return m_data_ptr[offset];
454  }
455 
457  virtual size_t size() const = 0;
458 
460  virtual void resize(const std::vector<size_t>& shape) = 0;
461 
463  virtual std::unique_ptr<ContainerInterface> copy() const = 0;
464  };
465 
466  template <template <class...> class Container>
467  struct ContainerWrapper : public ContainerInterface {
469  Container<T> m_container;
470 
471  ~ContainerWrapper() = default;
472 
473  ContainerWrapper(const ContainerWrapper&) = delete;
474 
475  ContainerWrapper(ContainerWrapper&&) = default;
476 
477  template <typename... Args>
478  ContainerWrapper(Args&&... args) : m_container(std::forward<Args>(args)...) {
479  m_data_ptr = m_container.data();
480  }
481 
482  size_t size() const final {
483  return m_container.size();
484  }
485 
486  template <typename T2>
488  -> decltype((void)std::declval<Container<T2>>().resize(std::vector<size_t>{}), void()) {
489  m_container.resize(shape);
490  }
491 
492  template <typename T2>
493  auto resizeImpl(const std::vector<size_t>& shape) -> decltype((void)std::declval<Container<T2>>().resize(size_t{}), void()) {
494  auto new_size = std::accumulate(shape.begin(), shape.end(), 1u, std::multiplies<size_t>());
495  m_container.resize(new_size);
496  }
497 
505  void resize(const std::vector<size_t>& shape) final {
506  resizeImpl<T>(shape);
507  m_data_ptr = m_container.data();
508  }
509 
511  return Euclid::make_unique<ContainerWrapper>(m_container);
512  }
513  };
514 
516 
520  explicit NdArray(const self_type* other);
521 
527  size_t get_offset(const std::vector<size_t>& coords) const;
528 
534  size_t get_offset(std::vector<size_t> coords, const std::string& attr) const;
535 
539  void update_strides();
540 
544  template <typename... D>
545  T& at_helper(std::vector<size_t>& acc, size_t i, D... rest);
546 
551 
555  T& at_helper(std::vector<size_t>& acc, const std::string& attr);
556 
560  template <typename... D>
561  const T& at_helper(std::vector<size_t>& acc, size_t i, D... rest) const;
562 
566  const T& at_helper(std::vector<size_t>& acc) const;
567 
568  template <typename... D>
569  self_type& reshape_helper(std::vector<size_t>& acc, size_t i, D... rest);
570 
572 };
573 
577 template <typename T>
578 std::ostream& operator<<(std::ostream& out, const NdArray<T>& ndarray);
579 
580 } // namespace NdArray
581 } // namespace Euclid
582 
583 #define NDARRAY_IMPL
585 #undef NDARRAY_IMPL
586 
587 #endif // ALEXANDRIA_NDARRAY_H
bool operator>(const Iterator &other)
ContainerWrapper(const ContainerWrapper &)=delete
const std::vector< size_t > shape() const
Definition: NdArray.h:286
Iterator & operator-=(size_t n)
std::vector< size_t > m_shape
Definition: NdArray.h:435
self_type & reshape_helper(std::vector< size_t > &acc, size_t i, D...rest)
bool operator==(const self_type &b) const
size_t size() const
virtual void resize(const std::vector< size_t > &shape)=0
Resize container.
bool operator!=(const self_type &b) const
const std::vector< std::string > & attributes() const
T end(T...args)
NdArray(const std::vector< size_t > &shape_)
auto resizeImpl(const std::vector< size_t > &shape) -> decltype((void) std::declval< Container< T2 >>().resize(std::vector< size_t >
Definition: NdArray.h:487
Iterator< false > iterator
Definition: NdArray.h:174
STL class.
std::unique_ptr< ContainerInterface > copy() const final
Expected to generate a deep copy of the underlying data.
Definition: NdArray.h:510
self_type & concatenate(const self_type &other)
std::vector< size_t > m_stride_size
Definition: NdArray.h:435
NdArray(const std::initializer_list< size_t > &shape_)
Definition: NdArray.h:253
T & at_helper(std::vector< size_t > &acc, size_t i, D...rest)
virtual ~NdArray()=default
T declval(T...args)
Iterator & operator+=(size_t n)
bool operator<(const Iterator &other)
Iterator(ContainerInterface *container_ptr, size_t offset)
NdArray & operator=(const NdArray &)=default
NdArray copy() const
Definition: NdArray.h:277
bool operator!=(const Iterator &other) const
std::shared_ptr< ContainerInterface > m_container
Definition: NdArray.h:515
T & at(const std::vector< size_t > &coords)
STL class.
Iterator< true > const_iterator
Definition: NdArray.h:173
STL class.
T begin(T...args)
void resize(const std::vector< size_t > &shape) final
Definition: NdArray.h:505
typename std::conditional< Const, const T, T >::type value_t
Definition: NdArray.h:72
NdArray< T > self_type
Definition: NdArray.h:51
size_t get_offset(const std::vector< size_t > &coords) const
std::vector< std::string > m_attr_names
Definition: NdArray.h:436
self_type & reshape(const std::vector< size_t > new_shape)
bool operator==(const Iterator &other) const
T accumulate(T...args)
ContainerInterface * m_container_ptr
Definition: NdArray.h:64
STL class.
virtual std::unique_ptr< ContainerInterface > copy() const =0
Expected to generate a deep copy of the underlying data.