STIR  6.2.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 - 2024, 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 
35 #include "stir/ByteOrder.h"
36 #include "stir/IndexRange.h"
37 #include "stir/deprecated.h"
38 #include "stir/shared_ptr.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 
72 template <int num_dimensions, typename elemT>
73 class Array : public NumericVectorWithOffset<Array<num_dimensions - 1, elemT>, elemT>
74 {
75 #ifdef SWIG
76  // work-around swig problem. It gets confused when using a private (or protected)
77  // typedef in a definition of a public typedef/member
78  public:
79 #else
80 private:
81 #endif
82  typedef Array<num_dimensions, elemT> self;
83  typedef NumericVectorWithOffset<Array<num_dimensions - 1, elemT>, elemT> base_type;
84 
85 public:
87  typedef typename base_type::value_type value_type;
89  typedef typename base_type::reference reference;
91  typedef typename base_type::difference_type difference_type;
92  typedef typename base_type::size_type size_type;
93  typedef typename base_type::iterator iterator;
96 #ifdef ARRAY_FULL
97 
103  typedef elemT full_value_type;
104  typedef full_value_type* full_pointer;
105  typedef const full_value_type* const_full_pointer;
106  typedef full_value_type& full_reference;
107  typedef const full_value_type& const_full_reference;
108 # ifndef ARRAY_FULL2
109  typedef FullArrayIterator<typename base_type::iterator,
111  typename Array<num_dimensions - 1, elemT>::full_iterator,
112  elemT,
113  full_reference,
114  full_pointer>
116 
118  typedef FullArrayIterator<typename base_type::const_iterator,
119  typename Array<num_dimensions - 1, elemT>::const_full_iterator,
120  elemT,
121  const_full_reference,
122  const_full_pointer>
124 # else // ARRAY_FULL2
126 
127  typedef FullArrayConstIterator<num_dimensions, elemT, const_full_reference, const_full_pointer> const_full_iterator;
128 
129 # endif
130 
131 #endif
132 public:
134  inline Array();
135 
137  inline explicit Array(const IndexRange<num_dimensions>&);
138 
140 
149  inline Array(const IndexRange<num_dimensions>& range, shared_ptr<elemT[]> data_sptr);
150 
151 #ifndef SWIG
152  // swig 2.0.4 gets confused by base_type (due to numeric template arguments)
153  // therefore, we declare this constructor using the "self" type,
154  // i.e. it's just a copy-constructor.
155  // This is less powerful as in C++, but swig-generated interfaces don't need to know about the base_type anyway
157  inline Array(const base_type& t);
158 #endif
159 
161  // implementation needed as the above doesn't disable the auto-generated copy-constructor
162  inline Array(const self& t);
163 
165  inline ~Array() override;
166 
168  // implementation in .h because of templates/friends/whatever, see https://stackoverflow.com/a/61020224
169  friend inline void swap(Array& first, Array& second) // nothrow
170  {
171  using std::swap;
172  // swap the members of two objects
173  swap(static_cast<base_type&>(first), static_cast<base_type&>(second));
174  swap(first._allocated_full_data_ptr, second._allocated_full_data_ptr);
175  }
176 
178 
179  Array(Array&& other) noexcept;
180 
182 
183  Array& operator=(Array other);
184 
187  inline full_iterator begin_all();
190  inline const_full_iterator begin_all() const;
192  inline const_full_iterator begin_all_const() const;
194  inline full_iterator end_all();
196  inline const_full_iterator end_all() const;
198  inline const_full_iterator end_all_const() const;
200 
201  inline IndexRange<num_dimensions> get_index_range() const;
202 
204  inline size_t size_all() const;
205 
207 
215  inline virtual void resize(const IndexRange<num_dimensions>& range);
216 
218  virtual inline void grow(const IndexRange<num_dimensions>& range);
219 
221  inline elemT sum() const;
222 
224  inline elemT sum_positive() const;
225 
227  inline elemT find_max() const;
228 
230  inline elemT find_min() const;
231 
233 
236  inline void fill(const elemT& n);
238  inline void apply_lower_threshold(const elemT& l);
239 
241  inline void apply_upper_threshold(const elemT& u);
242 
244 
250  inline bool is_regular() const;
251 
253 
254  bool get_regular_range(BasicCoordinate<num_dimensions, int>& min, BasicCoordinate<num_dimensions, int>& max) const;
255 
257  inline Array<num_dimensions - 1, elemT>& operator[](int i);
258 
260  inline const Array<num_dimensions - 1, elemT>& operator[](int i) const;
261 
263  inline elemT& operator[](const BasicCoordinate<num_dimensions, int>& c);
264 
266  // TODO alternative return value: elemT
267  inline const elemT& operator[](const BasicCoordinate<num_dimensions, int>& c) const;
268 
270 
271  inline Array<num_dimensions - 1, elemT>& at(int i);
272 
273  inline const Array<num_dimensions - 1, elemT>& at(int i) const;
274 
275  inline elemT& at(const BasicCoordinate<num_dimensions, int>& c);
276 
277  inline const elemT& at(const BasicCoordinate<num_dimensions, int>& c) const;
279 
281  template <typename elemT2>
282  STIR_DEPRECATED inline void axpby(const elemT2 a, const Array& x, const elemT2 b, const Array& y);
283 
285  inline void xapyb(const Array& x, const elemT a, const Array& y, const elemT b);
286 
288  inline void xapyb(const Array& x, const Array& a, const Array& y, const Array& b);
289 
291  template <class T>
292  inline void sapyb(const T& a, const Array& y, const T& b);
293 
295 
296  bool is_contiguous() const;
298 
300  inline elemT* get_full_data_ptr();
301 
303  inline const elemT* get_const_full_data_ptr() const;
304 
306  inline void release_full_data_ptr();
307 
309  inline void release_const_full_data_ptr() const;
311 
312 private:
314  // This variable is declared mutable such that get_const_full_data_ptr() can change it.
315  mutable bool _full_pointer_access;
316 
318  shared_ptr<elemT[]> _allocated_full_data_ptr;
319 
321 
327  inline void init(const IndexRange<num_dimensions>& range, elemT* const data_ptr, bool copy_data);
328  // Make sure that we can access init() recursively
329  template <int num_dimensions2, class elemT2>
330  friend class Array;
331 };
332 
333 /**************************************************
334  (partial) specialisation for 1 dimensional arrays
335  **************************************************/
336 
338 template <class elemT>
339 class Array<1, elemT> : public NumericVectorWithOffset<elemT, elemT>
340 #ifdef STIR_USE_BOOST
341  ,
342  boost::operators<Array<1, elemT>, NumericVectorWithOffset<elemT, elemT>>,
343  boost::operators<Array<1, elemT>>,
344  boost::operators<Array<1, elemT>, elemT>
345 #endif
346 {
347 #ifdef SWIG
348  // work-around swig problem. It gets confused when using a private (or protected)
349  // typedef in a definition of a public typedef/member
350  public:
351 #else
352 private:
353 #endif
355  typedef Array<1, elemT> self;
356 
357 public:
359 
360  typedef typename base_type::value_type value_type;
361  typedef typename base_type::reference reference;
362  typedef typename base_type::const_reference const_reference;
363  typedef typename base_type::difference_type difference_type;
364  typedef typename base_type::size_type size_type;
365  typedef typename base_type::iterator iterator;
366  typedef typename base_type::const_iterator const_iterator;
368 
373  typedef iterator full_iterator;
374 
376  typedef const_iterator const_full_iterator;
377 
378 public:
380  inline Array();
381 
383  inline explicit Array(const IndexRange<1>& range);
384 
386  inline Array(const int min_index, const int max_index);
387 
389 
395  inline Array(const IndexRange<1>& range, shared_ptr<elemT[]> data_sptr);
396 
398 
401  inline Array(const IndexRange<1>& range, const elemT* const data_ptr);
402 
405 
407  // implementation needed as the above doesn't replace the normal copy-constructor
408  // and the auto-generated is disabled because of the move constructor
409  inline Array(const self& t);
410 
412 
413  Array(Array&& other) noexcept;
414 
416  inline ~Array() override;
417 
419  // implementation in .h because of templates/friends/whatever, see https://stackoverflow.com/a/61020224
420  friend inline void swap(Array& first, Array& second) // nothrow
421  {
422  swap(static_cast<base_type&>(first), static_cast<base_type&>(second));
423  }
424 
426  inline Array& operator=(const Array& other);
427 
430  inline full_iterator begin_all();
433  inline const_full_iterator begin_all() const;
435  inline const_full_iterator begin_all_const() const;
437  inline full_iterator end_all();
439  inline const_full_iterator end_all() const;
441  inline const_full_iterator end_all_const() const;
443 
445  inline IndexRange<1> get_index_range() const;
446 
448  inline size_t size_all() const;
449 
451  inline virtual void grow(const IndexRange<1>& range);
452 
453  // Array::grow initialises new elements to 0
454  inline void grow(const int min_index, const int max_index) override;
455 
457  inline virtual void resize(const IndexRange<1>& range);
458 
459  // Array::resize initialises new elements to 0
460  inline void resize(const int min_index, const int max_index) override;
461 
463 
464  bool is_contiguous() const
466  {
467  return true;
468  }
470  inline elemT* get_full_data_ptr()
471  {
472  return this->get_data_ptr();
473  }
474 
476  inline const elemT* get_const_full_data_ptr() const
477  {
478  return this->get_const_data_ptr();
479  }
480 
482  inline void release_full_data_ptr()
483  {
484  this->release_data_ptr();
485  }
486 
488  inline void release_const_full_data_ptr() const
489  {
490  this->release_const_data_ptr();
491  }
493 
495  inline elemT sum() const;
496 
498  inline elemT sum_positive() const;
499 
501  inline elemT find_max() const;
502 
504  inline elemT find_min() const;
505 
507  inline bool is_regular() const;
508 
510  bool get_regular_range(BasicCoordinate<1, int>& min, BasicCoordinate<1, int>& max) const;
511 
512 #ifndef STIR_USE_BOOST
513 
514  /* KT 31/01/2000 I had to add these functions here, although they are
515  in NumericVectorWithOffset already.
516  Reason: we allow addition (and similar operations) of tensors of
517  different sizes. This implies that operator+= can call a 'grow'
518  on retval. For this to work, retval should be an Array, not
519  its base_type (which happens if these function are not repeated
520  in this class).
521  Complicated...
522  */
524  inline self operator+(const base_type& iv) const;
525 
527  inline self operator-(const base_type& iv) const;
528 
530  inline self operator*(const base_type& iv) const;
531 
533  inline self operator/(const base_type& iv) const;
534 
536  inline self operator+(const elemT a) const;
537 
539  inline self operator-(const elemT a) const;
540 
542  inline self operator*(const elemT a) const;
543 
545  inline self operator/(const elemT a) const;
546 
547 #endif // boost
548 
550  inline elemT& operator[](int i);
551 
553  inline const elemT& operator[](int i) const;
554 
556  inline const elemT& operator[](const BasicCoordinate<1, int>& c) const;
557 
559  inline elemT& operator[](const BasicCoordinate<1, int>& c);
560 
562 
563  inline elemT& at(int i);
564 
565  inline const elemT& at(int i) const;
566 
567  inline elemT& at(const BasicCoordinate<1, int>& c);
568 
569  inline const elemT& at(const BasicCoordinate<1, int>& c) const;
571 
572 private:
573  // Make sure we can call init() recursively.
574  template <int num_dimensions2, class elemT2>
575  friend class Array;
576 
578 
581  inline void init(const IndexRange<1>& range, elemT* const data_ptr, bool copy_data);
582 };
583 
584 END_NAMESPACE_STIR
585 
586 #ifdef ARRAY_FULL
587 # ifndef ARRAY_FULL2
588 # include "FullArrayIterator.h"
589 # else
590 # include "FullArrayIterator2.h"
591 # include "FullArrayConstIterator.h"
592 # endif
593 #endif
594 
595 #include "stir/Array.inl"
596 
597 #endif // __Array_H__
#define STIR_DEPRECATED
Deprecation macro.
Definition: deprecated.h:19
This file declares the stir::ByteOrder class.
iterator full_iterator
Iterator type for going through all elements.
Definition: Array.h:373
defines the stir::NumericVectorWithOffset class
elemT * get_full_data_ptr()
member function for access to the data via a elemT*
Definition: Array.h:470
friend void swap(Array &first, Array &second)
Swap content/members of 2 objects.
Definition: Array.h:169
This class defines ranges which can be &#39;irregular&#39;.
Definition: ArrayFunctionObject.h:32
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 (or corresponding b...
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:123
const elemT * get_const_full_data_ptr() const
member function for access to the data via a const elemT*
Definition: Array.h:476
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:115
void release_full_data_ptr()
signal end of access to elemT*
Definition: Array.h:482
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:360
void release_const_full_data_ptr() const
signal end of access to const elemT*
Definition: Array.h:488
friend void swap(Array &first, Array &second)
Swap content/members of 2 objects.
Definition: Array.h:420
const_iterator const_full_iterator
Iterator type for going through all elements of a const object.
Definition: Array.h:376
The 1-dimensional (partial) specialisation of Array.
Definition: Array.h:339
This file defines the stir::IndexRange class.
This class defines multi-dimensional (numeric) arrays.
Definition: Array.h:73
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