STIR 6.4.0
ArrayFunction.inl
Go to the documentation of this file.
1/*
2 Copyright (C) 2000 PARAPET partners
3 Copyright (C) 2000- 2007, Hammersmith Imanet Ltd
4 This file is part of STIR.
5
6 SPDX-License-Identifier: Apache-2.0 AND License-ref-PARAPET-license
7
8 See STIR/LICENSE.txt for details
9*/
26#include "stir/modulo.h"
27
28#include <cmath>
29#include <complex>
30#ifdef BOOST_NO_STDC_NAMESPACE
31namespace std
32{
33using ::log;
34using ::exp;
35} // namespace std
36#endif
37
38START_NAMESPACE_STIR
39
40//----------------------------------------------------------------------
41// element wise and in place numeric functions
42//----------------------------------------------------------------------
43
44template <class elemT>
45inline Array<1, elemT>&
47{
48 for (int i = v.get_min_index(); i <= v.get_max_index(); i++)
49 v[i] = std::log(v[i]);
50 return v;
51}
52
53template <int num_dimensions, class elemT>
54inline Array<num_dimensions, elemT>&
56{
57 for (int i = v.get_min_index(); i <= v.get_max_index(); i++)
58 in_place_log(v[i]);
59 return v;
60}
61
62template <class elemT>
63inline Array<1, elemT>&
65{
66 for (int i = v.get_min_index(); i <= v.get_max_index(); i++)
67 v[i] = std::exp(v[i]);
68 return v;
69}
70
71template <int num_dimensions, class elemT>
72inline Array<num_dimensions, elemT>&
74{
75 for (int i = v.get_min_index(); i <= v.get_max_index(); i++)
76 in_place_exp(v[i]);
77 return v;
78}
79
80template <class elemT>
81inline Array<1, elemT>&
83{
84 for (int i = v.get_min_index(); i <= v.get_max_index(); i++)
85 if (v[i] < 0)
86 v[i] = -v[i];
87 return v;
88}
89
90template <int num_dimensions, class elemT>
91inline Array<num_dimensions, elemT>&
93{
94 for (int i = v.get_min_index(); i <= v.get_max_index(); i++)
95 in_place_abs(v[i]);
96 return v;
97}
98
99template <class T, class FUNCTION>
100inline T&
101in_place_apply_function(T& v, FUNCTION f)
102{
103 typename T::full_iterator iter = v.begin_all();
104 const typename T::full_iterator end_iter = v.end_all();
105 while (iter != end_iter)
106 {
107 *iter = f(*iter);
108 ++iter;
109 }
110 return v;
111}
112
113template <int num_dim, typename elemT, typename FunctionObjectPtr>
114inline void
116{
117 assert(array.is_regular());
118 const int outer_min_index = array.get_min_index();
119 const int outer_max_index = array.get_max_index();
120
121 // construct a vector with a full_iterator for every array[i]
123#ifndef _MSC_VER
124 typename
125#endif
126 Array<num_dim - 1, elemT>::full_iterator>
127 full_iterators(outer_min_index, outer_max_index);
128 for (int i = outer_min_index; i <= outer_max_index; ++i)
129 full_iterators[i] = array[i].begin_all();
130
131 // allocate 1d array
132 Array<1, elemT> array1d(outer_min_index, outer_max_index);
133
134 while (full_iterators[outer_min_index] != array[outer_min_index].end_all())
135 {
136 // copy elements into 1d array
137 for (int i = outer_min_index; i <= outer_max_index; ++i)
138 array1d[i] = *full_iterators[i];
139
140 // apply function
141 (*f)(array1d);
142
143 // put results back
144 // and increment full_iterators to do next index
145 for (int i = outer_min_index; i <= outer_max_index; ++i)
146 *full_iterators[i]++ = array1d[i];
147 }
148}
149
150template <int num_dim, typename elemT, typename FunctionObjectPtr>
151inline void
153{
154 assert(in_array.is_regular());
155 assert(out_array.is_regular());
156 const int in_min_index = in_array.get_min_index();
157 const int in_max_index = in_array.get_max_index();
158 const int out_min_index = out_array.get_min_index();
159 const int out_max_index = out_array.get_max_index();
160
161 // construct a vector with a full_iterator for every in_array[i]
162 VectorWithOffset<typename Array<num_dim - 1, elemT>::const_full_iterator> in_full_iterators(in_min_index, in_max_index);
163 for (int i = in_min_index; i <= in_max_index; ++i)
164 in_full_iterators[i] = in_array[i].begin_all();
165 // same for out_array[i]
166 VectorWithOffset<typename Array<num_dim - 1, elemT>::full_iterator> out_full_iterators(out_min_index, out_max_index);
167 for (int i = out_min_index; i <= out_max_index; ++i)
168 out_full_iterators[i] = out_array[i].begin_all();
169
170 // allocate 1d array
171 Array<1, elemT> in_array1d(in_min_index, in_max_index);
172 Array<1, elemT> out_array1d(out_min_index, out_max_index);
173
174 while (in_full_iterators[in_min_index] != in_array[in_min_index].end_all())
175 {
176 assert(out_full_iterators[out_min_index] != out_array[out_min_index].end_all());
177 // copy elements into 1d array
178 // increment in_full_iterators for next index
179 for (int i = in_min_index; i <= in_max_index; ++i)
180 in_array1d[i] = *(in_full_iterators[i]++);
181
182 // apply function
183 (*f)(out_array1d, in_array1d);
184 assert(out_array1d.get_min_index() == out_min_index);
185 assert(out_array1d.get_max_index() == out_max_index);
186
187 // put results back
188 // increment out_full_iterators for next index
189 for (int i = out_min_index; i <= out_max_index; ++i)
190 *(out_full_iterators[i]++) = out_array1d[i];
191 }
192 assert(out_full_iterators[out_min_index] == out_array[out_min_index].end_all());
193}
194
195template <int num_dim, typename elemT, typename FunctionObjectPtrIter>
196inline void
198 FunctionObjectPtrIter start,
199 FunctionObjectPtrIter stop)
200{
201 assert(start + num_dim == stop);
202 assert(num_dim > 1);
204
205 ++start;
206 for (typename Array<num_dim, elemT>::iterator restiter = array.begin(); restiter != array.end(); ++restiter)
207 in_place_apply_array_functions_on_each_index(*restiter, start, stop);
208}
209
210template <typename elemT, typename FunctionObjectPtrIter>
211inline void
212in_place_apply_array_functions_on_each_index(Array<1, elemT>& array, FunctionObjectPtrIter start, FunctionObjectPtrIter stop)
213{
214 assert(start + 1 == stop);
215 (**start)(array);
216}
217
218template <int num_dim, typename elemT, typename FunctionObjectPtrIter>
219inline void
221 const Array<num_dim, elemT>& in_array,
222 FunctionObjectPtrIter start,
223 FunctionObjectPtrIter stop)
224{
225 assert(start + num_dim == stop);
226 assert(num_dim > 1);
227
228 assert(out_array.is_regular());
229 BasicCoordinate<num_dim, int> tmp_out_min_indices, tmp_out_max_indices;
230 out_array.get_regular_range(tmp_out_min_indices, tmp_out_max_indices);
231 tmp_out_min_indices[1] = in_array.get_min_index();
232 tmp_out_max_indices[1] = in_array.get_max_index();
233 Array<num_dim, elemT> tmp_out_array(IndexRange<num_dim>(tmp_out_min_indices, tmp_out_max_indices));
234
235 for (int i = in_array.get_min_index(); i <= in_array.get_max_index(); ++i)
236 apply_array_functions_on_each_index(tmp_out_array[i], in_array[i], start + 1, stop);
237
238 apply_array_function_on_1st_index(out_array, tmp_out_array, *start);
239}
240
241// specialisation that uses ArrayFunctionObject::is_trivial etc
242template <int num_dim, typename elemT>
243inline void
245 const Array<num_dim, elemT>& in_array,
246 ActualFunctionObjectPtrIter start,
247 ActualFunctionObjectPtrIter stop)
248{
249 assert(start + num_dim == stop);
250 assert(num_dim > 1);
251
252 // cerr << "apply_array_functions_on_each_index dim " << num_dim << std::endl;
253 if ((**start).is_trivial())
254 {
255 for (int i = max(out_array.get_min_index(), in_array.get_min_index());
256 i <= min(out_array.get_max_index(), in_array.get_max_index());
257 ++i)
258 apply_array_functions_on_each_index(out_array[i], in_array[i], start + 1, stop);
259 }
260 else
261 {
262 assert(out_array.is_regular());
263
264 IndexRange<1> influencing_indices;
265 if ((**start).get_influencing_indices(influencing_indices,
266 IndexRange<1>(out_array.get_min_index(), out_array.get_max_index()))
267 == Succeeded::no)
268 influencing_indices = IndexRange<1>(influencing_indices.get_min_index(), in_array.get_max_index());
269 else
270 {
271 influencing_indices = IndexRange<1>(max(influencing_indices.get_min_index(), in_array.get_min_index()),
272 min(influencing_indices.get_max_index(), in_array.get_max_index()));
273 }
274 BasicCoordinate<num_dim, int> tmp_out_min_indices, tmp_out_max_indices;
275 out_array.get_regular_range(tmp_out_min_indices, tmp_out_max_indices);
276 tmp_out_min_indices[1] = influencing_indices.get_min_index();
277 tmp_out_max_indices[1] = influencing_indices.get_max_index();
278 Array<num_dim, elemT> tmp_out_array(IndexRange<num_dim>(tmp_out_min_indices, tmp_out_max_indices));
279
280 for (int i = influencing_indices.get_min_index(); i <= influencing_indices.get_max_index(); ++i)
281 apply_array_functions_on_each_index(tmp_out_array[i], in_array[i], start + 1, stop);
282
283 apply_array_function_on_1st_index(out_array, tmp_out_array, *start);
284 }
285}
286
287// has to be here to get general 1D specialisation to compile
288template <typename elemT>
289inline void
291 const Array<1, elemT>& in_array,
292 ActualFunctionObjectPtrIter start,
293 ActualFunctionObjectPtrIter stop)
294{
295 assert(start + 1 == stop);
296 (**start)(out_array, in_array);
297}
298
299template <typename elemT, typename FunctionObjectPtrIter>
300inline void
302 const Array<1, elemT>& in_array,
303 FunctionObjectPtrIter start,
304 FunctionObjectPtrIter stop)
305{
306 assert(start + 1 == stop);
307 (**start)(out_array, in_array);
308}
309
310/******************* functions that copy arrays using transformed indices *****/
311
312template <int num_dimensions, typename elemT>
313inline void
314transform_array_to_periodic_indices(Array<num_dimensions, elemT>& out_array, const Array<num_dimensions, elemT>& in_array)
315{
316 assert(norm(get_min_indices(out_array)) < .01); // check out_array is 0-based
317
318 BasicCoordinate<num_dimensions, int> min_indices, max_indices;
319
320 assert(out_array.get_regular_range(min_indices, max_indices));
321 out_array.get_regular_range(min_indices, max_indices);
322 const BasicCoordinate<num_dimensions, int> out_sizes = max_indices - min_indices + 1;
323 {
324 BasicCoordinate<num_dimensions, int> index = get_min_indices(in_array);
325 do
326 {
327 out_array[modulo(index, out_sizes)] = in_array[index];
328 } while (next(index, in_array));
329 }
330}
331
332template <int num_dimensions, typename elemT>
333inline void
334transform_array_from_periodic_indices(Array<num_dimensions, elemT>& out_array, const Array<num_dimensions, elemT>& in_array)
335{
336 assert(norm(get_min_indices(in_array)) < .01); // check in_array is 0-based
337
338 BasicCoordinate<num_dimensions, int> min_indices, max_indices;
339
340 assert(in_array.get_regular_range(min_indices, max_indices));
341 in_array.get_regular_range(min_indices, max_indices);
342 const BasicCoordinate<num_dimensions, int> in_sizes = max_indices - min_indices + 1;
343
344 BasicCoordinate<num_dimensions, int> index = get_min_indices(out_array);
345 do
346 {
347 out_array[index] = in_array[modulo(index, in_sizes)];
348 } while (next(index, out_array));
349}
350
351END_NAMESPACE_STIR
This file declares class stir::BasicCoordinate and some functions acting on stir::BasicCoordinate obj...
a variety of useful functions for indexing stir::Array objects
This class defines multi-dimensional (numeric) arrays.
Definition Array.h:78
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
bool is_regular() const
checks if the index range is 'regular'
Definition Array.inl:469
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
A templated class for vectors, but with indices starting not from 0.
Definition VectorWithOffset.h:65
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
Array< 1, elemT > & in_place_abs(Array< 1, elemT > &v)
Replace elements by their absolute value, 1D version.
Definition ArrayFunction.inl:82
void in_place_apply_array_function_on_1st_index(Array< num_dim, elemT > &array, FunctionObjectPtr f)
Apply a function object on all possible 1d arrays extracted by keeping all indices fixed,...
Definition ArrayFunction.inl:115
T & in_place_apply_function(T &v, FUNCTION f)
apply any function(object) to each element of the multi-dimensional array
Definition ArrayFunction.inl:101
void apply_array_function_on_1st_index(Array< num_dim, elemT > &out_array, const Array< num_dim, elemT > &in_array, FunctionObjectPtr f)
apply any function(object) to each element of the multi-dimensional array, storing results in a diffe...
Definition ArrayFunction.inl:152
void in_place_apply_array_functions_on_each_index(Array< num_dim, elemT > &array, FunctionObjectPtrIter start, FunctionObjectPtrIter stop)
Apply a sequence of 1d array-function objects on every dimension of the input array.
Definition ArrayFunction.inl:197
void apply_array_functions_on_each_index(Array< num_dim, elemT > &out_array, const Array< num_dim, elemT > &in_array, FunctionObjectPtrIter start, FunctionObjectPtrIter stop)
Apply a sequence of 1d array-function objects on every dimension of the input array,...
Definition ArrayFunction.inl:220
Array< 1, elemT > & in_place_exp(Array< 1, elemT > &v)
Replace elements by their exponentiation, 1D version.
Definition ArrayFunction.inl:64
Array< 1, elemT > & in_place_log(Array< 1, elemT > &v)
Replace elements by their logarithm, 1D version.
Definition ArrayFunction.inl:46
double norm(const BasicCoordinate< num_dimensions, coordT > &p1)
compute sqrt(inner_product(p1,p1))
Definition BasicCoordinate.inl:426
defines stir::modulo() and related functions
BasicCoordinate< num_dimensions, int > get_min_indices(const Array< num_dimensions, T > &a)
Get the first multi-dimensional index of the array.
Definition array_index_functions.inl:100
bool next(BasicCoordinate< num_dimensions, int > &indices, const Array< num_dimensions2, T > &a)
Given an index into an array, increment it to the next one.
Definition array_index_functions.inl:107
double modulo(const double a, const double b)
Like std::fmod() but with guaranteed nonnegative result.
Definition modulo.h:52