STIR  6.3.0
Array.h
Go to the documentation of this file.
1 
2 /*
3  Copyright (C) 2000 PARAPET partners
4  Copyright (C) 2000 - 2011-10-14, Hammersmith Imanet Ltd
5  Copyright (C) 2011-07-01 - 2012, Kris Thielemans
6  Copyright (C) 2023 - 2025, University College London
7  This file is part of STIR.
8 
9  SPDX-License-Identifier: Apache-2.0 AND License-ref-PARAPET-license
10 
11  See STIR/LICENSE.txt for details
12 */
13 
14 #ifndef __stir_Array_H__
15 #define __stir_Array_H__
16 
17 #ifndef ARRAY_FULL
18 # define ARRAY_FULL
19 #endif
20 
32 #include "stir/ByteOrder.h"
33 #include "stir/IndexRange.h"
34 #include "stir/deprecated.h"
35 #include "stir/shared_ptr.h"
36 // include forward declaration to ensure consistency, as well as use of
37 // default parameters (if any)
38 #include "stir/ArrayFwd.h"
39 
40 START_NAMESPACE_STIR
41 class NumericType;
42 
43 #ifdef ARRAY_FULL
44 # ifndef ARRAY_FULL2
45 template <typename topleveliterT, typename restiterT, typename elemT, typename _Ref, typename _Ptr>
47 # else
48 template <int num_dimensions, typename elemT, typename _Ref, typename _Ptr>
49 class FullArrayIterator;
50 template <int num_dimensions, typename elemT, typename _Ref, typename _Ptr>
51 class FullArrayConstIterator;
52 # endif
53 
54 #endif
55 
76 template <int num_dimensions, typename elemT>
77 class Array : public NumericVectorWithOffset<Array<num_dimensions - 1, elemT>, elemT>
78 {
79 #ifdef STIR_COMPILING_SWIG_WRAPPER
80  // work-around swig problem. It gets confused when using a private (or protected)
81  // typedef in a definition of a public typedef/member
82 public:
83 #endif
84  typedef Array<num_dimensions, elemT> self;
85  typedef NumericVectorWithOffset<Array<num_dimensions - 1, elemT>, elemT> base_type;
86 
87 public:
89  typedef typename base_type::value_type value_type;
91  typedef typename base_type::reference reference;
93  typedef typename base_type::difference_type difference_type;
94  typedef typename base_type::size_type size_type;
95  typedef typename base_type::iterator iterator;
98 #ifdef ARRAY_FULL
99 
105  typedef elemT full_value_type;
106  typedef full_value_type* full_pointer;
107  typedef const full_value_type* const_full_pointer;
108  typedef full_value_type& full_reference;
109  typedef const full_value_type& const_full_reference;
110 # ifndef ARRAY_FULL2
111  typedef FullArrayIterator<typename base_type::iterator,
113  typename Array<num_dimensions - 1, elemT>::full_iterator,
114  elemT,
115  full_reference,
116  full_pointer>
118 
120  typedef FullArrayIterator<typename base_type::const_iterator,
121  typename Array<num_dimensions - 1, elemT>::const_full_iterator,
122  elemT,
123  const_full_reference,
124  const_full_pointer>
126 # else // ARRAY_FULL2
128 
129  typedef FullArrayConstIterator<num_dimensions, elemT, const_full_reference, const_full_pointer> const_full_iterator;
130 
131 # endif
132 
133 #endif
134 public:
136  inline Array();
137 
139  inline explicit Array(const IndexRange<num_dimensions>&);
140 
142 
151  inline Array(const IndexRange<num_dimensions>& range, shared_ptr<elemT[]> data_sptr);
152 
153 #ifndef SWIG
154  // swig 2.0.4 gets confused by base_type (due to numeric template arguments)
155  // therefore, we declare this constructor using the "self" type,
156  // i.e. it's just a copy-constructor.
157  // This is less powerful as in C++, but swig-generated interfaces don't need to know about the base_type anyway
159  inline Array(const base_type& t);
160 #endif
161 
163  // implementation needed as the above doesn't disable the auto-generated copy-constructor
164  inline Array(const self& t);
165 
167  inline ~Array() override;
168 
170  // implementation in .h because of templates/friends/whatever, see https://stackoverflow.com/a/61020224
171  friend inline void swap(Array& first, Array& second) // nothrow
172  {
173  using std::swap;
174  // swap the members of two objects
175  swap(static_cast<base_type&>(first), static_cast<base_type&>(second));
176  swap(first._allocated_full_data_ptr, second._allocated_full_data_ptr);
177  }
178 
180 
181  Array(Array&& other) noexcept;
182 
184 
185  Array& operator=(Array other);
186 
189  inline full_iterator begin_all();
192  inline const_full_iterator begin_all() const;
194  inline const_full_iterator begin_all_const() const;
196  inline full_iterator end_all();
198  inline const_full_iterator end_all() const;
200  inline const_full_iterator end_all_const() const;
202 
203  inline IndexRange<num_dimensions> get_index_range() const;
204 
206  inline size_t size_all() const;
207 
209 
218  inline virtual void resize(const IndexRange<num_dimensions>& range);
219 
221  virtual inline void grow(const IndexRange<num_dimensions>& range);
222 
224  inline elemT sum() const;
225 
227  inline elemT sum_positive() const;
228 
230  inline elemT find_max() const;
231 
233  inline elemT find_min() const;
234 
236 
239  inline void fill(const elemT& n);
241  inline void apply_lower_threshold(const elemT& l);
242 
244  inline void apply_upper_threshold(const elemT& u);
245 
247 
253  inline bool is_regular() const;
254 
256 
257  bool get_regular_range(BasicCoordinate<num_dimensions, int>& min, BasicCoordinate<num_dimensions, int>& max) const;
258 
260  inline Array<num_dimensions - 1, elemT>& operator[](int i);
261 
263  inline const Array<num_dimensions - 1, elemT>& operator[](int i) const;
264 
266  inline elemT& operator[](const BasicCoordinate<num_dimensions, int>& c);
267 
269  // TODO alternative return value: elemT
270  inline const elemT& operator[](const BasicCoordinate<num_dimensions, int>& c) const;
271 
273 
274  inline Array<num_dimensions - 1, elemT>& at(int i);
275 
276  inline const Array<num_dimensions - 1, elemT>& at(int i) const;
277 
278  inline elemT& at(const BasicCoordinate<num_dimensions, int>& c);
279 
280  inline const elemT& at(const BasicCoordinate<num_dimensions, int>& c) const;
282 
284 
285  // tedious reimplementation to fix return types. This could be avoided by using boost::operators.
286  // However, reimplementing them explicitly helps SWIG.
287  inline self& operator+=(const self& x)
288  {
289  base_type::operator+=(x);
290  return *this;
291  }
292  inline self& operator-=(const self& x)
293  {
294  base_type::operator-=(x);
295  return *this;
296  }
297  inline self& operator*=(const self& x)
298  {
299  base_type::operator*=(x);
300  return *this;
301  }
302  inline self& operator/=(const self& x)
303  {
304  base_type::operator/=(x);
305  return *this;
306  }
307  inline self& operator+=(const elemT x)
308  {
309  base_type::operator+=(x);
310  return *this;
311  }
312  inline self& operator-=(const elemT x)
313  {
314  base_type::operator-=(x);
315  return *this;
316  }
317  inline self& operator*=(const elemT x)
318  {
319  base_type::operator*=(x);
320  return *this;
321  }
322  inline self& operator/=(const elemT x)
323  {
324  base_type::operator/=(x);
325  return *this;
326  }
327  inline self operator+(const self& x) const
328  {
329  self c(*this);
330  return c += x;
331  }
332  inline self operator+(const elemT x) const
333  {
334  self c(*this);
335  return c += x;
336  }
337  inline self operator-(const self& x) const
338  {
339  self c(*this);
340  return c -= x;
341  }
342  inline self operator-(const elemT x) const
343  {
344  self c(*this);
345  return c -= x;
346  }
347  inline self operator*(const self& x) const
348  {
349  self c(*this);
350  return c *= x;
351  }
352  inline self operator*(const elemT x) const
353  {
354  self c(*this);
355  return c *= x;
356  }
357  inline self operator/(const self& x) const
358  {
359  self c(*this);
360  return c /= x;
361  }
362  inline self operator/(const elemT x) const
363  {
364  self c(*this);
365  return c /= x;
366  }
368 
370  template <typename elemT2>
371  STIR_DEPRECATED inline void axpby(const elemT2 a, const Array& x, const elemT2 b, const Array& y);
372 
374  inline void xapyb(const Array& x, const elemT a, const Array& y, const elemT b);
375 
377  inline void xapyb(const Array& x, const Array& a, const Array& y, const Array& b);
378 
380  template <class T>
381  inline void sapyb(const T& a, const Array& y, const T& b);
382 
384 
385  bool is_contiguous() const;
387 
389  inline elemT* get_full_data_ptr();
390 
392  inline const elemT* get_const_full_data_ptr() const;
393 
395  inline void release_full_data_ptr();
396 
398  inline void release_const_full_data_ptr() const;
400 
401 private:
403  // This variable is declared mutable such that get_const_full_data_ptr() can change it.
404  mutable bool _full_pointer_access;
405 
407  shared_ptr<elemT[]> _allocated_full_data_ptr;
408 
410 
416  inline void init_with_copy(const IndexRange<num_dimensions>& range, elemT const* const data_ptr);
418 
427  inline void init(const IndexRange<num_dimensions>& range, elemT* const data_ptr, bool copy_data);
428  // Make sure that we can access init() recursively
429  template <int num_dimensions2, class elemT2>
430  friend class Array;
431 
432  using base_type::grow;
433  using base_type::resize;
434 };
435 
436 /**************************************************
437  (partial) specialisation for 1 dimensional arrays
438  **************************************************/
439 
441 template <class elemT>
442 class Array<1, elemT> : public NumericVectorWithOffset<elemT, elemT>
443 {
444 #ifdef STIR_COMPILING_SWIG_WRAPPER
445  // work-around swig problem. It gets confused when using a private (or protected)
446  // typedef in a definition of a public typedef/member
447 public:
448 #endif
450  typedef Array<1, elemT> self;
451 
452 public:
454 
455  typedef typename base_type::value_type value_type;
456  typedef typename base_type::reference reference;
457  typedef typename base_type::const_reference const_reference;
458  typedef typename base_type::difference_type difference_type;
459  typedef typename base_type::size_type size_type;
460  typedef typename base_type::iterator iterator;
461  typedef typename base_type::const_iterator const_iterator;
463 
468  typedef iterator full_iterator;
469 
471  typedef const_iterator const_full_iterator;
472 
473 public:
475  inline Array();
476 
478  inline explicit Array(const IndexRange<1>& range);
479 
481  inline Array(const int min_index, const int max_index);
482 
484 
490  inline Array(const IndexRange<1>& range, shared_ptr<elemT[]> data_sptr);
491 
493 
496  inline Array(const IndexRange<1>& range, const elemT* const data_ptr);
497 
500 
502  // implementation needed as the above doesn't replace the normal copy-constructor
503  // and the auto-generated is disabled because of the move constructor
504  inline Array(const self& t);
505 
507 
508  Array(Array&& other) noexcept;
509 
511  inline ~Array() override;
512 
514  // implementation in .h because of templates/friends/whatever, see https://stackoverflow.com/a/61020224
515  friend inline void swap(Array& first, Array& second) // nothrow
516  {
517  swap(static_cast<base_type&>(first), static_cast<base_type&>(second));
518  }
519 
521  inline Array& operator=(const Array& other);
522 
525  inline full_iterator begin_all();
528  inline const_full_iterator begin_all() const;
530  inline const_full_iterator begin_all_const() const;
532  inline full_iterator end_all();
534  inline const_full_iterator end_all() const;
536  inline const_full_iterator end_all_const() const;
538 
540  inline IndexRange<1> get_index_range() const;
541 
543  inline size_t size_all() const;
544 
546  inline virtual void grow(const IndexRange<1>& range);
547 
548  // Array::grow initialises new elements to 0
549  inline void grow(const int min_index, const int max_index) override;
550 
552  inline virtual void resize(const IndexRange<1>& range);
553 
554  inline void resize(const int min_index, const int max_index, bool initialise_with_0);
556  inline void resize(const int min_index, const int max_index) override;
557 
559 
560  bool is_contiguous() const
562  {
563  return true;
564  }
566  inline elemT* get_full_data_ptr()
567  {
568  return this->get_data_ptr();
569  }
570 
572  inline const elemT* get_const_full_data_ptr() const
573  {
574  return this->get_const_data_ptr();
575  }
576 
578  inline void release_full_data_ptr()
579  {
580  this->release_data_ptr();
581  }
582 
584  inline void release_const_full_data_ptr() const
585  {
586  this->release_const_data_ptr();
587  }
589 
591  inline elemT sum() const;
592 
594  inline elemT sum_positive() const;
595 
597  inline elemT find_max() const;
598 
600  inline elemT find_min() const;
601 
603  inline bool is_regular() const;
604 
606  bool get_regular_range(BasicCoordinate<1, int>& min, BasicCoordinate<1, int>& max) const;
607 
608  /* Add numerical operators with correct return value, as opposed to those from the base class
609  */
611  inline self operator+(const base_type& iv) const;
612 
614  inline self operator-(const base_type& iv) const;
615 
617  inline self operator*(const base_type& iv) const;
618 
620  inline self operator/(const base_type& iv) const;
621 
623  inline self operator+(const elemT a) const;
624 
626  inline self operator-(const elemT a) const;
627 
629  inline self operator*(const elemT a) const;
630 
632  inline self operator/(const elemT a) const;
633 
635  inline elemT& operator[](int i);
636 
638  inline const elemT& operator[](int i) const;
639 
641  inline const elemT& operator[](const BasicCoordinate<1, int>& c) const;
642 
644  inline elemT& operator[](const BasicCoordinate<1, int>& c);
645 
647 
648  inline elemT& at(int i);
649 
650  inline const elemT& at(int i) const;
651 
652  inline elemT& at(const BasicCoordinate<1, int>& c);
653 
654  inline const elemT& at(const BasicCoordinate<1, int>& c) const;
656 private:
657  // Make sure we can call init() recursively.
658  template <int num_dimensions2, class elemT2>
659  friend class Array;
660 
662 
665  inline void init_with_copy(const IndexRange<1>& range, elemT const* const data_ptr);
667 
670  inline void init(const IndexRange<1>& range, elemT* const data_ptr, bool copy_data);
671 };
672 
673 END_NAMESPACE_STIR
674 
675 #ifdef ARRAY_FULL
676 # ifndef ARRAY_FULL2
677 # include "FullArrayIterator.h"
678 # else
679 # include "FullArrayIterator2.h"
680 # include "FullArrayConstIterator.h"
681 # endif
682 #endif
683 
684 #include "stir/Array.inl"
685 
686 #endif // __Array_H__
#define STIR_DEPRECATED
Deprecation macro.
Definition: deprecated.h:21
This file declares the stir::ByteOrder class.
forward declaration of stir::Array class for multi-dimensional (numeric) arrays
iterator full_iterator
Iterator type for going through all elements.
Definition: Array.h:468
defines the stir::NumericVectorWithOffset class
elemT * get_full_data_ptr()
member function for access to the data via a elemT*
Definition: Array.h:566
friend void swap(Array &first, Array &second)
Swap content/members of 2 objects.
Definition: Array.h:171
This class defines ranges which can be &#39;irregular&#39;.
Definition: ArrayFunctionObject.h:31
This file declares a deprecation macro.
Class FullArrayIterator implements (forward) iterators that go through all elements of an Array...
Definition: Array.h:46
Import of std::shared_ptr, std::dynamic_pointer_cast and std::static_pointer_cast into the stir names...
inline implementations for the stir::Array class
like VectorWithOffset, but with changes in various numeric operators
Definition: NumericVectorWithOffset.h:47
FullArrayIterator< typename base_type::const_iterator, typename Array< num_dimensions - 1, elemT >::const_full_iterator, elemT, const_full_reference, const_full_pointer > const_full_iterator
As full_iterator, but for const objects.
Definition: Array.h:125
const elemT * get_const_full_data_ptr() const
member function for access to the data via a const elemT*
Definition: Array.h:572
FullArrayIterator< typename base_type::iterator, typename Array< num_dimensions - 1, elemT >::full_iterator, elemT, full_reference, full_pointer > full_iterator
This defines an iterator type that iterates through all elements.
Definition: Array.h:117
void release_full_data_ptr()
signal end of access to elemT*
Definition: Array.h:578
base_type::value_type value_type
typedefs such that we do not need to have typename wherever we use these types defined in the base cl...
Definition: Array.h:455
void release_const_full_data_ptr() const
signal end of access to const elemT*
Definition: Array.h:584
friend void swap(Array &first, Array &second)
Swap content/members of 2 objects.
Definition: Array.h:515
const_iterator const_full_iterator
Iterator type for going through all elements of a const object.
Definition: Array.h:471
The 1-dimensional (partial) specialisation of Array.
Definition: Array.h:442
This file defines the stir::IndexRange class.
This class defines multi-dimensional (numeric) arrays.
Definition: Array.h:77
The (simple) 1 dimensional specialisation of IndexRange.
Definition: IndexRange.h:131
This file declares the stir::FullArrayIterator class.
elemT sum(IterT start, IterT end, elemT init)
Compute the sum of a sequence using operator+=(), using an initial value.
Definition: more_algorithms.inl:52