STIR 6.4.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
40START_NAMESPACE_STIR
41class NumericType;
42
43#ifdef ARRAY_FULL
44# ifndef ARRAY_FULL2
45template <typename topleveliterT, typename restiterT, typename elemT, typename _Ref, typename _Ptr>
46class FullArrayIterator;
47# else
48template <int num_dimensions, typename elemT, typename _Ref, typename _Ptr>
49class FullArrayIterator;
50template <int num_dimensions, typename elemT, typename _Ref, typename _Ptr>
51class FullArrayConstIterator;
52# endif
53
54#endif
55
75
76template <int num_dimensions, typename elemT>
77class 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
82public:
83#endif
84 typedef Array<num_dimensions, elemT> self;
85 typedef NumericVectorWithOffset<Array<num_dimensions - 1, elemT>, elemT> base_type;
86
87public:
89
90 typedef typename base_type::value_type value_type;
91 typedef typename base_type::reference reference;
92 typedef typename base_type::const_reference const_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;
96 typedef typename base_type::const_iterator const_iterator;
98#ifdef ARRAY_FULL
103
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
112 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
133#endif
134public:
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
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
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
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 {
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
386 bool is_contiguous() const;
387
389 inline elemT* get_full_data_ptr();
390
392 inline const elemT* get_const_full_data_ptr() const;
393
396
398 inline void release_const_full_data_ptr() const;
400
401private:
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
441template <class elemT>
442class 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
447public:
448#endif
450 typedef Array<1, elemT> self;
451
452public:
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
472
473public:
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
526 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
561 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;
656private:
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
673END_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__
forward declaration of stir::Array class for multi-dimensional (numeric) arrays
inline implementations for the stir::Array class
This file declares the stir::ByteOrder class.
This file declares the stir::FullArrayIterator class.
This file defines the stir::IndexRange class.
defines the stir::NumericVectorWithOffset class
This class defines multi-dimensional (numeric) arrays.
Definition Array.h:78
virtual void resize(const IndexRange< num_dimensions > &range)
change the array to a new range of indices, new elements are set to 0
Definition Array.inl:62
const Array< num_dimensions - 1, elemT > & operator[](int i) const
array access, read-only
Definition Array.inl:493
Array(const IndexRange< num_dimensions > &)
Construct an Array of given range of indices, elements are initialised to 0.
Definition Array.inl:115
full_iterator begin_all()
start value for iterating through all elements in the array, see full_iterator
Definition Array.inl:213
elemT & operator[](const BasicCoordinate< num_dimensions, int > &c)
allow array-style access given a BasicCoordinate to specify the indices, read/write
Definition Array.inl:499
FullArrayIterator< typename base_type::iterator, typename Array< num_dimensions - 1, std::complex< float > >::full_iterator, std::complex< float >, full_reference, full_pointer > full_iterator
Definition Array.h:117
Array< num_dimensions - 1, elemT > & operator[](int i)
allow array-style access, read/write
Definition Array.inl:486
const elemT & operator[](const BasicCoordinate< num_dimensions, int > &c) const
array access given a BasicCoordinate to specify the indices, read-only
Definition Array.inl:505
virtual void grow(const IndexRange< num_dimensions > &range)
alias for resize()
Definition Array.inl:103
const_full_iterator begin_all() const
start value for iterating through all elements in the (const) array, see full_iterator
Definition Array.inl:239
Array()
Construct an empty Array.
Definition Array.inl:109
bool is_contiguous() const
return if the array is contiguous in memory
Definition Array.inl:44
void apply_lower_threshold(const elemT &l)
Sets elements below value to the value.
Definition Array.inl:449
size_t size_all() const
return the total number of elements in this array
Definition Array.inl:262
const elemT * get_const_full_data_ptr() const
member function for access to the data via a const elemT*
Definition Array.inl:311
bool get_regular_range(BasicCoordinate< num_dimensions, int > &min, BasicCoordinate< num_dimensions, int > &max) const
find regular range, returns false if the range is not regular
Definition Array.inl:477
elemT sum_positive() const
return sum of all positive elements
Definition Array.inl:370
Array & operator=(Array other)
assignment operator
Definition Array.inl:176
void release_full_data_ptr()
signal end of access to elemT*
Definition Array.inl:329
Array(const base_type &t)
Construct an Array from an object of its base_type.
Definition Array.inl:148
elemT find_max() const
return maximum of all the elements
Definition Array.inl:387
STIR_DEPRECATED void axpby(const elemT2 a, const Array &x, const elemT2 b, const Array &y)
void xapyb(const Array &x, const Array &a, const Array &y, const Array &b)
set values of the array to x*a+y*b, where a and b are arrays
Definition Array.inl:563
void xapyb(const Array &x, const elemT a, const Array &y, const elemT b)
set values of the array to x*a+y*b, where a and b are scalar
Definition Array.inl:546
elemT * get_full_data_ptr()
member function for access to the data via a elemT*
Definition Array.inl:292
Array(Array &&other) noexcept
move constructor
Array(const self &t)
Copy constructor.
Definition Array.inl:136
base_type::value_type value_type
Definition Array.h:90
bool is_regular() const
checks if the index range is 'regular'
Definition Array.inl:469
const_full_iterator end_all_const() const
end value for iterating through all elements in the array, see full_iterator
Definition Array.inl:196
elemT find_min() const
return minimum of all the elements
Definition Array.inl:413
void sapyb(const T &a, const Array &y, const T &b)
set values of the array to self*a+y*b where a and b are scalar or arrays
Definition Array.inl:585
void release_const_full_data_ptr() const
signal end of access to const elemT*
Definition Array.inl:345
full_iterator end_all()
end value for iterating through all elements in the array, see full_iterator
Definition Array.inl:185
void fill(const elemT &n)
Fill elements with value n.
Definition Array.inl:439
const_full_iterator begin_all_const() const
start value for iterating through all elements in the array, see full_iterator
Definition Array.inl:226
elemT sum() const
return sum of all elements
Definition Array.inl:353
Array(const IndexRange< num_dimensions > &range, shared_ptr< elemT[]> data_sptr)
Construct an Array pointing to existing contiguous data.
Definition Array.inl:129
FullArrayIterator< typename base_type::const_iterator, typename Array< num_dimensions - 1, std::complex< float > >::const_full_iterator, std::complex< float >, const_full_reference, const_full_pointer > const_full_iterator
Definition Array.h:125
friend void swap(Array &first, Array &second)
Swap content/members of 2 objects.
Definition Array.h:171
const_full_iterator end_all() const
end value for iterating through all elements in the (const) array, see full_iterator
Definition Array.inl:206
~Array() override
virtual destructor, frees up any allocated memory
Definition Array.inl:157
void apply_upper_threshold(const elemT &u)
Sets elements above value to the value.
Definition Array.inl:459
class BasicCoordinate<int num_dimensions, typename coordT> defines num_dimensions -dimensional coordi...
Definition BasicCoordinate.h:57
Class FullArrayIterator implements (forward) iterators that go through all elements of an Array.
Definition FullArrayIterator.h:49
This class defines ranges which can be 'irregular'.
Definition IndexRange.h:69
like VectorWithOffset, but with changes in various numeric operators
Definition NumericVectorWithOffset.h:48
NumericVectorWithOffset & operator+=(const NumericVectorWithOffset &v)
Definition NumericVectorWithOffset.inl:137
NumericVectorWithOffset(const VectorWithOffset< Array< num_dimensions - 1, elemT > > &t)
virtual void grow(const int min_index, const int max_index)
Definition VectorWithOffset.inl:491
virtual void resize(const int min_index, const int max_index)
Definition VectorWithOffset.inl:426
This file declares a deprecation macro.
#define STIR_DEPRECATED
Deprecation macro.
Definition deprecated.h:21
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
Import of std::shared_ptr, std::dynamic_pointer_cast and std::static_pointer_cast into the stir names...