STIR 6.4.0
Array.inl
Go to the documentation of this file.
1//
2//
3/*
4 Copyright (C) 2000 PARAPET partners
5 Copyright (C) 2000 - 2011-01-11, Hammersmith Imanet Ltd
6 Copyright (C) 2011-07-01 - 2012, Kris Thielemans
7 Copyright (C) 2023 - 2025, University College London
8 This file is part of STIR.
9
10 SPDX-License-Identifier: Apache-2.0 AND License-ref-PARAPET-license
11
12 See STIR/LICENSE.txt for details
13*/
24// include for min,max definitions
25#include <algorithm>
26#include "stir/assign.h"
28#include "stir/error.h"
29
30#ifdef TESTARRAYDEBINFO
31# include "stir/info.h"
32# define DEBINFO(args) info(args)
33#else
34# define DEBINFO(ARGS)
35#endif
36
37START_NAMESPACE_STIR
38
39/**********************************************
40 inlines for Array<num_dimensions, elemT>
41 **********************************************/
42template <int num_dimensions, typename elemT>
43bool
45{
46 auto mem = &(*this->begin_all());
47 for (auto i = this->get_min_index(); i <= this->get_max_index(); ++i)
48 {
49 if (!(*this)[i].is_contiguous())
50 return false;
51 if (i == this->get_max_index())
52 return true;
53 mem += (*this)[i].size_all();
54 if (mem != &(*(*this)[i + 1].begin_all()))
55 return false;
56 }
57 return true;
58}
59
60template <int num_dimensions, typename elemT>
61void
63{
65 typename base_type::iterator iter = this->begin();
66 typename IndexRange<num_dimensions>::const_iterator range_iter = range.begin();
67 for (; iter != this->end(); ++iter, ++range_iter)
68 (*iter).resize(*range_iter);
69}
70
71template <int num_dimensions, typename elemT>
72void
73Array<num_dimensions, elemT>::init(const IndexRange<num_dimensions>& range, elemT* const data_ptr, bool copy_data)
74{
75 base_type::resize(range.get_min_index(), range.get_max_index());
76 auto iter = this->begin();
77 auto range_iter = range.begin();
78 auto ptr = data_ptr;
79 for (; iter != this->end(); ++iter, ++range_iter)
80 {
81 (*iter).init(*range_iter, ptr, copy_data);
82 ptr += range_iter->size_all();
83 }
84}
85
86template <int num_dimensions, typename elemT>
87void
88Array<num_dimensions, elemT>::init_with_copy(const IndexRange<num_dimensions>& range, elemT const* const data_ptr)
89{
90 base_type::resize(range.get_min_index(), range.get_max_index());
91 auto iter = this->begin();
92 auto range_iter = range.begin();
93 auto ptr = data_ptr;
94 for (; iter != this->end(); ++iter, ++range_iter)
95 {
96 (*iter).init_with_copy(*range_iter, ptr);
97 ptr += range_iter->size_all();
98 }
99}
100
101template <int num_dimensions, typename elemT>
102void
107
108template <int num_dimensions, typename elemT>
109Array<num_dimensions, elemT>::Array()
110 : base_type(),
111 _allocated_full_data_ptr(nullptr)
112{}
113
114template <int num_dimensions, typename elemT>
115Array<num_dimensions, elemT>::Array(const IndexRange<num_dimensions>& range)
116 : base_type(),
117 _allocated_full_data_ptr(new elemT[range.size_all()])
118{
119 // DEBINFO("Array constructor range " + std::to_string(reinterpret_cast<std::size_t>(this->_allocated_full_data_ptr)) + " of
120 // size "
121 // + std::to_string(range.size_all())); set elements to zero
122 std::for_each(this->_allocated_full_data_ptr.get(), this->_allocated_full_data_ptr.get() + range.size_all(), [](elemT& e) {
123 assign(e, 0);
124 });
125 this->init(range, this->_allocated_full_data_ptr.get(), false);
126}
127
128template <int num_dimensions, typename elemT>
129Array<num_dimensions, elemT>::Array(const IndexRange<num_dimensions>& range, shared_ptr<elemT[]> data_sptr)
130{
131 this->_allocated_full_data_ptr = data_sptr;
132 this->init(range, this->_allocated_full_data_ptr.get(), false);
133}
134
135template <int num_dimensions, typename elemT>
136Array<num_dimensions, elemT>::Array(const self& t)
137 : base_type(),
138 _allocated_full_data_ptr(new elemT[t.size_all()])
140 this->init(t.get_index_range(), this->_allocated_full_data_ptr.get(), false);
141 std::copy(t.begin_all(), t.end_all(), this->_allocated_full_data_ptr.get());
142 DEBINFO("constructor " + std::to_string(num_dimensions) + "copy of size " + std::to_string(this->size_all()));
143}
144
145#ifndef SWIG
146// swig cannot parse this ATM, but we don't need it anyway in the wrappers
147template <int num_dimensions, typename elemT>
148Array<num_dimensions, elemT>::Array(const base_type& t)
149 : base_type(t),
150 _allocated_full_data_ptr(nullptr)
152 DEBINFO("constructor basetype " + std::to_string(num_dimensions) + " of size " + std::to_string(this->size_all()));
153}
154#endif
155
156template <int num_dimensions, typename elemT>
158{
159 if (this->_allocated_full_data_ptr)
160 {
161 // DEBINFO("Array destructor full_data_ptr " + std::to_string(reinterpret_cast<std::size_t>(this->_allocated_full_data_ptr))
162 // + " of size " + std::to_string(this->size_all())); delete [] this->_allocated_full_data_ptr;
163 }
165
166template <int num_dimensions, typename elemT>
167Array<num_dimensions, elemT>::Array(Array<num_dimensions, elemT>&& other) noexcept
168 : Array()
169{
170 swap(*this, other);
171 DEBINFO("move constructor " + std::to_string(num_dimensions) + "copy of size " + std::to_string(this->size_all()));
172}
173
174template <int num_dimensions, typename elemT>
176Array<num_dimensions, elemT>::operator=(Array<num_dimensions, elemT> other)
177{
178 swap(*this, other);
179 DEBINFO("Array= " + std::to_string(num_dimensions) + "copy of size " + std::to_string(this->size_all()));
180 return *this;
181}
182
183template <int num_dimensions, typename elemT>
186{
187 // note this value is fixed by the current convention in full_iterator::operator++()
188 return full_iterator(this->end(),
189 this->end(),
193
194template <int num_dimensions, typename elemT>
197{
198 return const_full_iterator(this->end(),
199 this->end(),
203
204template <int num_dimensions, typename elemT>
207{
208 return this->end_all_const();
209}
210
211template <int num_dimensions, typename elemT>
214{
215 if (this->begin() == this->end())
216 {
217 // empty array
218 return end_all();
219 }
220 else
221 return full_iterator(this->begin(), this->end(), this->begin()->begin_all(), this->begin()->end_all());
222}
223
224template <int num_dimensions, typename elemT>
228 if (this->begin() == this->end())
229 {
230 // empty array
231 return end_all();
232 }
233 else
234 return const_full_iterator(this->begin(), this->end(), this->begin()->begin_all_const(), this->begin()->end_all_const());
235}
236
237template <int num_dimensions, typename elemT>
240{
242}
243
244template <int num_dimensions, class elemT>
246Array<num_dimensions, elemT>::get_index_range() const
247{
248 VectorWithOffset<IndexRange<num_dimensions - 1>> range(this->get_min_index(), this->get_max_index());
249
250 typename VectorWithOffset<IndexRange<num_dimensions - 1>>::iterator range_iter = range.begin();
251 const_iterator array_iter = this->begin();
252
253 for (; range_iter != range.end(); range_iter++, array_iter++)
254 {
255 *range_iter = (*array_iter).get_index_range();
256 }
258}
259
260template <int num_dimensions, typename elemT>
261size_t
264 this->check_state();
265 size_t acc = 0;
266#ifdef STIR_OPENMP
267# if _OPENMP >= 201107
268# pragma omp parallel for reduction(+ : acc)
269# endif
270#endif
271 for (int i = this->get_min_index(); i <= this->get_max_index(); i++)
272 acc += this->num[i].size_all();
273 return acc;
274}
275
290template <int num_dimensions, typename elemT>
291elemT*
293{
294 this->_full_pointer_access = true;
295 if (!this->is_contiguous())
296 error("Array::get_full_data_ptr() called for non-contiguous array.");
297 return &(*this->begin_all());
298};
299
309template <int num_dimensions, typename elemT>
310const elemT*
312{
313 this->_full_pointer_access = true;
314 if (!this->is_contiguous())
315 error("Array::get_const_full_data_ptr() called for non-contiguous array.");
316 return &(*this->begin_all_const());
317};
318
327template <int num_dimensions, typename elemT>
328void
330{
331 assert(this->_full_pointer_access);
332
333 this->_full_pointer_access = false;
334}
335
342
343template <int num_dimensions, typename elemT>
344void
346{
347 assert(this->_full_pointer_access);
348 this->_full_pointer_access = false;
349}
350
351template <int num_dimensions, typename elemT>
352elemT
354{
355 this->check_state();
356 typename HigherPrecision<elemT>::type acc;
357 assign(acc, 0);
358#ifdef STIR_OPENMP
359# if _OPENMP >= 201107
360# pragma omp parallel for reduction(+ : acc)
361# endif
362#endif
363 for (int i = this->get_min_index(); i <= this->get_max_index(); i++)
364 acc += this->num[i].sum();
365 return static_cast<elemT>(acc);
366}
367
368template <int num_dimensions, typename elemT>
369elemT
371{
372 this->check_state();
373 typename HigherPrecision<elemT>::type acc;
374 assign(acc, 0);
375#ifdef STIR_OPENMP
376# if _OPENMP >= 201107
377# pragma omp parallel for reduction(+ : acc)
378# endif
379#endif
380 for (int i = this->get_min_index(); i <= this->get_max_index(); i++)
381 acc += this->num[i].sum_positive();
382 return static_cast<elemT>(acc);
383}
384
385template <int num_dimensions, typename elemT>
386elemT
388{
389 this->check_state();
390 if (this->size() > 0)
391 {
392 elemT maxval = this->num[this->get_min_index()].find_max();
393#ifdef STIR_OPENMP
394# if _OPENMP >= 201107
395# pragma omp parallel for reduction(max : maxval)
396# endif
397#endif
398 for (int i = this->get_min_index() + 1; i <= this->get_max_index(); i++)
399 {
400 maxval = std::max(this->num[i].find_max(), maxval);
401 }
402 return maxval;
403 }
404 else
405 {
406 // TODO we should return elemT::minimum or something
407 return 0;
408 }
409}
410
411template <int num_dimensions, typename elemT>
412elemT
414{
415 this->check_state();
416 if (this->size() > 0)
417 {
418 elemT minval = this->num[this->get_min_index()].find_min();
419#ifdef STIR_OPENMP
420# if _OPENMP >= 201107
421# pragma omp parallel for reduction(min : minval)
422# endif
423#endif
424 for (int i = this->get_min_index() + 1; i <= this->get_max_index(); i++)
425 {
426 minval = std::min(this->num[i].find_min(), minval);
427 }
428 return minval;
429 }
430 else
431 {
432 // TODO we should return elemT::maximum or something
433 return 0;
434 }
435}
436
437template <int num_dimensions, typename elemT>
438void
440{
441 this->check_state();
442 for (int i = this->get_min_index(); i <= this->get_max_index(); i++)
443 this->num[i].fill(n);
444 this->check_state();
445}
446
447template <int num_dimensions, typename elemT>
448void
450{
451 this->check_state();
452 for (int i = this->get_min_index(); i <= this->get_max_index(); i++)
453 this->num[i].apply_lower_threshold(l);
454 this->check_state();
455}
456
457template <int num_dimensions, typename elemT>
458void
460{
461 this->check_state();
462 for (int i = this->get_min_index(); i <= this->get_max_index(); i++)
463 this->num[i].apply_upper_threshold(u);
464 this->check_state();
465}
466
467template <int num_dimensions, typename elemT>
468bool
470{
471 return get_index_range().is_regular();
472}
473
474// TODO terribly inefficient at the moment
475template <int num_dimensions, typename elemT>
476bool
483
484template <int num_dimension, typename elemT>
485Array<num_dimension - 1, elemT>&
490
491template <int num_dimension, typename elemT>
492const Array<num_dimension - 1, elemT>&
497template <int num_dimensions, typename elemT>
498elemT&
503template <int num_dimensions, typename elemT>
504const elemT&
509
510template <int num_dimension, typename elemT>
511Array<num_dimension - 1, elemT>&
512Array<num_dimension, elemT>::at(int i)
513{
514 return base_type::at(i);
515}
516
517template <int num_dimension, typename elemT>
518const Array<num_dimension - 1, elemT>&
519Array<num_dimension, elemT>::at(int i) const
520{
521 return base_type::at(i);
522}
523template <int num_dimensions, typename elemT>
524elemT&
525Array<num_dimensions, elemT>::at(const BasicCoordinate<num_dimensions, int>& c)
526{
527 return (*this).at(c[1]).at(cut_first_dimension(c));
528}
529template <int num_dimensions, typename elemT>
530const elemT&
531Array<num_dimensions, elemT>::at(const BasicCoordinate<num_dimensions, int>& c) const
532{
533 return (*this).at(c[1]).at(cut_first_dimension(c));
534}
535
536template <int num_dimensions, typename elemT>
537template <typename elemT2>
538void
539Array<num_dimensions, elemT>::axpby(const elemT2 a, const Array& x, const elemT2 b, const Array& y)
540{
542}
543
544template <int num_dimensions, typename elemT>
545void
546Array<num_dimensions, elemT>::xapyb(const Array& x, const elemT a, const Array& y, const elemT b)
547{
548 this->check_state();
549 if ((this->get_index_range() != x.get_index_range()) || (this->get_index_range() != y.get_index_range()))
550 error("Array::xapyb: index ranges don't match");
551
552 typename Array::full_iterator this_iter = this->begin_all();
553 typename Array::const_full_iterator x_iter = x.begin_all();
554 typename Array::const_full_iterator y_iter = y.begin_all();
555 while (this_iter != this->end_all())
556 {
557 *this_iter++ = (*x_iter++) * a + (*y_iter++) * b;
558 }
559}
560
561template <int num_dimensions, typename elemT>
562void
563Array<num_dimensions, elemT>::xapyb(const Array& x, const Array& a, const Array& y, const Array& b)
564{
565 this->check_state();
566 if ((this->get_index_range() != x.get_index_range()) || (this->get_index_range() != y.get_index_range())
567 || (this->get_index_range() != a.get_index_range()) || (this->get_index_range() != b.get_index_range()))
568 error("Array::xapyb: index ranges don't match");
569
570 typename Array::full_iterator this_iter = this->begin_all();
571 typename Array::const_full_iterator x_iter = x.begin_all();
572 typename Array::const_full_iterator y_iter = y.begin_all();
573 typename Array::const_full_iterator a_iter = a.begin_all();
574 typename Array::const_full_iterator b_iter = b.begin_all();
575
576 while (this_iter != this->end_all())
577 {
578 *this_iter++ = (*x_iter++) * (*a_iter++) + (*y_iter++) * (*b_iter++);
579 }
580}
581
582template <int num_dimensions, typename elemT>
583template <class T>
584void
585Array<num_dimensions, elemT>::sapyb(const T& a, const Array& y, const T& b)
586{
587 this->xapyb(*this, a, y, b);
588}
589
590/**********************************************
591 inlines for Array<1, elemT>
592 **********************************************/
593template <class elemT>
594void
595Array<1, elemT>::init_with_copy(const IndexRange<1>& range, elemT const* const data_ptr)
596{
597 base_type::init_with_copy(range.get_min_index(), range.get_max_index(), data_ptr);
598}
599
600template <class elemT>
601void
602Array<1, elemT>::init(const IndexRange<1>& range, elemT* const data_ptr, bool copy_data)
603{
604 base_type::init(range.get_min_index(), range.get_max_index(), data_ptr, copy_data);
605}
606
607template <class elemT>
608void
609Array<1, elemT>::resize(const int min_index, const int max_index, bool initialise_with_0)
610{
611 this->check_state();
612 const int oldstart = this->get_min_index();
613 const size_type oldlength = this->size();
614
615 base_type::resize(min_index, max_index);
616
617 if (!initialise_with_0)
618 {
619 this->check_state();
620 return;
621 }
622
623 if (oldlength == 0)
624 {
625 for (int i = this->get_min_index(); i <= this->get_max_index(); i++)
626 assign(this->num[i], 0);
627 }
628 else
629 {
630 for (int i = this->get_min_index(); i < oldstart && i <= this->get_max_index(); ++i)
631 assign(this->num[i], 0);
632 for (int i = std::max(static_cast<int>(oldstart + oldlength), this->get_min_index()); i <= this->get_max_index(); ++i)
633 assign(this->num[i], 0);
634 }
635 this->check_state();
636}
637
638template <class elemT>
639void
640Array<1, elemT>::resize(const int min_index, const int max_index)
641{
642 resize(min_index, max_index, true);
643}
644
645template <class elemT>
646void
648{
649 resize(range.get_min_index(), range.get_max_index());
650}
651
652template <class elemT>
653void
654Array<1, elemT>::grow(const int min_index, const int max_index)
655{
656 resize(min_index, max_index);
657}
658
659template <class elemT>
660void
662{
663 grow(range.get_min_index(), range.get_max_index());
664}
665
666template <class elemT>
667Array<1, elemT>::Array()
668 : base_type()
669{}
670
671template <class elemT>
672Array<1, elemT>::Array(const IndexRange<1>& range)
673 : base_type()
674{
675 grow(range);
676}
677
678template <class elemT>
679Array<1, elemT>::Array(const int min_index, const int max_index)
680 : base_type()
681{
682 grow(min_index, max_index);
683}
684
685template <class elemT>
686Array<1, elemT>::Array(const IndexRange<1>& range, shared_ptr<elemT[]> data_sptr)
687 : base_type(range.get_min_index(), range.get_max_index(), data_sptr)
688{}
689
690template <class elemT>
691Array<1, elemT>::Array(const IndexRange<1>& range, const elemT* const data_ptr)
692 : base_type(range.get_min_index(), range.get_max_index(), data_ptr)
693{}
694
695template <class elemT>
696Array<1, elemT>::Array(const base_type& il)
697 : base_type(il)
698{}
699
700template <typename elemT>
701Array<1, elemT>::Array(const Array<1, elemT>& other)
702 : base_type(other)
703{}
704
705template <typename elemT>
707{}
708
709template <typename elemT>
710Array<1, elemT>::Array(Array<1, elemT>&& other) noexcept
711 : Array()
712{
713 swap(*this, other);
714}
715
716template <typename elemT>
719{
720 // use the base_type assignment, as this tries to avoid reallocating memory
721 base_type::operator=(other);
722 return *this;
723}
724
725template <typename elemT>
728{
729 return this->begin();
730}
731
732template <typename elemT>
735{
736 return this->begin();
737}
738
739template <typename elemT>
742{
743 return this->end();
744}
745
746template <typename elemT>
749{
750 return this->end();
751}
752
753template <typename elemT>
756{
757 return this->begin();
758}
759
760template <typename elemT>
763{
764 return this->end();
765}
766
767template <typename elemT>
769Array<1, elemT>::get_index_range() const
770{
771 return IndexRange<1>(this->get_min_index(), this->get_max_index());
772}
773
774template <typename elemT>
775size_t
777{
778 return this->size();
779}
780
781template <class elemT>
782elemT
784{
785 this->check_state();
786 typename HigherPrecision<elemT>::type acc;
787 assign(acc, 0);
788#ifdef STIR_OPENMP
789# if _OPENMP >= 201107
790# pragma omp parallel for reduction(+ : acc)
791# endif
792#endif
793 for (int i = this->get_min_index(); i <= this->get_max_index(); ++i)
794 acc += this->num[i];
795 return static_cast<elemT>(acc);
796};
797
798template <class elemT>
799elemT
801{
802 this->check_state();
803 typename HigherPrecision<elemT>::type acc;
804 assign(acc, 0);
805#ifdef STIR_OPENMP
806# if _OPENMP >= 201107
807# pragma omp parallel for reduction(+ : acc)
808# endif
809#endif
810 for (int i = this->get_min_index(); i <= this->get_max_index(); i++)
811 {
812 if (this->num[i] > 0)
813 acc += this->num[i];
814 }
815 return static_cast<elemT>(acc);
816};
817
818template <class elemT>
819elemT
821{
822 this->check_state();
823 if (this->size() > 0)
824 {
825 return *std::max_element(this->begin(), this->end());
826 }
827 else
828 {
829 // TODO return elemT::minimum or so
830 return 0;
831 }
832 this->check_state();
833};
834
835template <class elemT>
836elemT
838{
839 this->check_state();
840 if (this->size() > 0)
841 {
842 return *std::min_element(this->begin(), this->end());
843 }
844 else
845 {
846 // TODO return elemT::maximum or so
847 return 0;
848 }
849 this->check_state();
850};
851
852template <typename elemT>
853bool
855{
856 return true;
857}
858
859template <typename elemT>
860bool
862{
863 const IndexRange<1> range = get_index_range();
864 return range.get_regular_range(min, max);
865}
866
867/* KT 31/01/2000 I had to add these functions here, although they are
868in NumericVectorWithOffset already.
869Reason: we allow addition (and similar operations) of tensors of
870different sizes. This implies that operator+= can call a 'grow'
871on retval. For this to work, retval should be a Array, not
872its base_type (which happens if these function are not repeated
873in this class).
874Complicated...
875*/
876template <class elemT>
878Array<1, elemT>::operator+(const base_type& iv) const
879{
880 this->check_state();
881 Array<1, elemT> retval(*this);
882 return retval += iv;
883};
884
885template <class elemT>
887Array<1, elemT>::operator-(const base_type& iv) const
888{
889 this->check_state();
890 Array<1, elemT> retval(*this);
891 return retval -= iv;
892}
893template <class elemT>
895Array<1, elemT>::operator*(const base_type& iv) const
896{
897 this->check_state();
898 Array<1, elemT> retval(*this);
899 return retval *= iv;
900}
901
902template <class elemT>
904Array<1, elemT>::operator/(const base_type& iv) const
905{
906 this->check_state();
907 Array<1, elemT> retval(*this);
908 return retval /= iv;
909}
910
911template <class elemT>
913Array<1, elemT>::operator+(const elemT a) const
914{
915 this->check_state();
916 Array<1, elemT> retval(*this);
917 return (retval += a);
918};
919
920template <class elemT>
922Array<1, elemT>::operator-(const elemT a) const
923{
924 this->check_state();
925 Array<1, elemT> retval(*this);
926 return (retval -= a);
927};
928
929template <class elemT>
931Array<1, elemT>::operator*(const elemT a) const
932{
933 this->check_state();
934 Array<1, elemT> retval(*this);
935 return (retval *= a);
936};
937
938template <class elemT>
940Array<1, elemT>::operator/(const elemT a) const
941{
942 this->check_state();
943 Array<1, elemT> retval(*this);
944 return (retval /= a);
945};
946
947template <typename elemT>
948const elemT&
950{
951 return base_type::operator[](i);
952};
953
954template <typename elemT>
955elemT&
957{
958 return base_type::operator[](i);
959};
960
961template <typename elemT>
962const elemT&
964{
965 return (*this)[c[1]];
966};
967
968template <typename elemT>
969elemT&
971{
972 return (*this)[c[1]];
973};
974
975template <typename elemT>
976const elemT&
977Array<1, elemT>::at(int i) const
978{
979 return base_type::at(i);
980};
981
982template <typename elemT>
983elemT&
984Array<1, elemT>::at(int i)
985{
986 return base_type::at(i);
987};
988
989template <typename elemT>
990const elemT&
991Array<1, elemT>::at(const BasicCoordinate<1, int>& c) const
992{
993 return (*this).at(c[1]);
994};
995
996template <typename elemT>
997elemT&
998Array<1, elemT>::at(const BasicCoordinate<1, int>& c)
999{
1000 return (*this).at(c[1]);
1001};
1002
1003END_NAMESPACE_STIR
1004
1005#undef DEBINFO
class stir::HigherPrecision
defines the stir::assign function to assign values to different data types
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
full_iterator begin_all()
start value for iterating through all elements in the array, see full_iterator
Definition Array.inl:213
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
Array< num_dimensions - 1, elemT > & operator[](int i)
allow array-style access, read/write
Definition Array.inl:486
virtual void grow(const IndexRange< num_dimensions > &range)
alias for resize()
Definition Array.inl:103
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
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 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
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
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
friend void swap(Array &first, Array &second)
Definition Array.h:171
~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
This class defines ranges which can be 'irregular'.
Definition IndexRange.h:69
size_t size_all() const
return the total number of elements in this range
Definition IndexRange.inl:71
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 IndexRange.cxx:29
A templated class for vectors, but with indices starting not from 0.
Definition VectorWithOffset.h:65
iterator begin()
use to initialise an iterator to the first element of the vector
Definition VectorWithOffset.inl:190
int get_max_index() const
get value of last valid index
Definition VectorWithOffset.inl:131
int get_min_index() const
get value of first valid index
Definition VectorWithOffset.inl:124
virtual void resize(const int min_index, const int max_index)
change the range of the vector, new elements are set to T()
Definition VectorWithOffset.inl:426
iterator end()
iterator 'past' the last element of the vector
Definition VectorWithOffset.inl:206
T & operator[](int i)
allow array-style access, read/write
Definition VectorWithOffset.inl:139
Array< num_dimensions - 1, std::complex< float > > * num
Definition VectorWithOffset.h:370
Declaration of stir::error()
BasicCoordinate< num_dimensions - 1, coordT > cut_first_dimension(const BasicCoordinate< num_dimensions, coordT > &c)
make a shorter BasicCoordinate, by cutting the first element from c
Definition BasicCoordinate.inl:477
void error(const char *const s,...)
Print error with format string a la printf and throw exception.
Definition error.cxx:42
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
Declaration of stir::info()