source: Sophya/trunk/SophyaExt/Blitz/blitz/array/slicing.cc@ 2937

Last change on this file since 2937 was 221, checked in by ansari, 26 years ago

Creation module DPC/Blitz (blitz 0.4) Reza 09/04/99

File size: 9.5 KB
Line 
1#ifndef BZ_ARRAYSLICING_CC
2#define BZ_ARRAYSLICING_CC
3
4#ifndef BZ_ARRAY_H
5 #error <blitz/array/slicing.cc> must be included via <blitz/array.h>
6#endif
7
8BZ_NAMESPACE(blitz)
9
10/*
11 * These routines make the array a view of a portion of another array.
12 * They all work by first referencing the other array, and then slicing.
13 */
14
15template<class P_numtype, int N_rank>
16void Array<P_numtype, N_rank>::constructSubarray(
17 Array<T_numtype, N_rank>& array, const RectDomain<N_rank>& subdomain)
18{
19 reference(array);
20 for (int i=0; i < N_rank; ++i)
21 slice(i, subdomain[i]);
22}
23
24template<class P_numtype, int N_rank>
25void Array<P_numtype, N_rank>::constructSubarray(
26 Array<T_numtype, N_rank>& array, Range r0)
27{
28 reference(array);
29 slice(0, r0);
30}
31
32template<class P_numtype, int N_rank>
33void Array<P_numtype, N_rank>::constructSubarray(
34 Array<T_numtype, N_rank>& array, Range r0, Range r1)
35{
36 reference(array);
37 slice(0, r0);
38 slice(1, r1);
39}
40
41template<class P_numtype, int N_rank>
42void Array<P_numtype, N_rank>::constructSubarray(
43 Array<T_numtype, N_rank>& array, Range r0, Range r1, Range r2)
44{
45 reference(array);
46 slice(0, r0);
47 slice(1, r1);
48 slice(2, r2);
49}
50
51template<class P_numtype, int N_rank>
52void Array<P_numtype, N_rank>::constructSubarray(
53 Array<T_numtype, N_rank>& array, Range r0, Range r1, Range r2, Range r3)
54{
55 reference(array);
56 slice(0, r0);
57 slice(1, r1);
58 slice(2, r2);
59 slice(3, r3);
60}
61
62template<class P_numtype, int N_rank>
63void Array<P_numtype, N_rank>::constructSubarray(
64 Array<T_numtype, N_rank>& array, Range r0, Range r1, Range r2, Range r3,
65 Range r4)
66{
67 reference(array);
68 slice(0, r0);
69 slice(1, r1);
70 slice(2, r2);
71 slice(3, r3);
72 slice(4, r4);
73}
74
75template<class P_numtype, int N_rank>
76void Array<P_numtype, N_rank>::constructSubarray(
77 Array<T_numtype, N_rank>& array, Range r0, Range r1, Range r2, Range r3,
78 Range r4, Range r5)
79{
80 reference(array);
81 slice(0, r0);
82 slice(1, r1);
83 slice(2, r2);
84 slice(3, r3);
85 slice(4, r4);
86 slice(5, r5);
87}
88
89template<class P_numtype, int N_rank>
90void Array<P_numtype, N_rank>::constructSubarray(
91 Array<T_numtype, N_rank>& array, Range r0, Range r1, Range r2, Range r3,
92 Range r4, Range r5, Range r6)
93{
94 reference(array);
95 slice(0, r0);
96 slice(1, r1);
97 slice(2, r2);
98 slice(3, r3);
99 slice(4, r4);
100 slice(5, r5);
101 slice(6, r6);
102}
103
104template<class P_numtype, int N_rank>
105void Array<P_numtype, N_rank>::constructSubarray(
106 Array<T_numtype, N_rank>& array, Range r0, Range r1, Range r2, Range r3,
107 Range r4, Range r5, Range r6, Range r7)
108{
109 reference(array);
110 slice(0, r0);
111 slice(1, r1);
112 slice(2, r2);
113 slice(3, r3);
114 slice(4, r4);
115 slice(5, r5);
116 slice(6, r6);
117 slice(7, r7);
118}
119
120template<class P_numtype, int N_rank>
121void Array<P_numtype, N_rank>::constructSubarray(
122 Array<T_numtype, N_rank>& array, Range r0, Range r1, Range r2, Range r3,
123 Range r4, Range r5, Range r6, Range r7, Range r8)
124{
125 reference(array);
126 slice(0, r0);
127 slice(1, r1);
128 slice(2, r2);
129 slice(3, r3);
130 slice(4, r4);
131 slice(5, r5);
132 slice(6, r6);
133 slice(7, r7);
134 slice(8, r8);
135}
136
137template<class P_numtype, int N_rank>
138void Array<P_numtype, N_rank>::constructSubarray(
139 Array<T_numtype, N_rank>& array, Range r0, Range r1, Range r2, Range r3,
140 Range r4, Range r5, Range r6, Range r7, Range r8, Range r9)
141{
142 reference(array);
143 slice(0, r0);
144 slice(1, r1);
145 slice(2, r2);
146 slice(3, r3);
147 slice(4, r4);
148 slice(5, r5);
149 slice(6, r6);
150 slice(7, r7);
151 slice(8, r8);
152 slice(9, r9);
153}
154
155template<class P_numtype, int N_rank>
156void Array<P_numtype, N_rank>::constructSubarray(
157 Array<T_numtype, N_rank>& array, Range r0, Range r1, Range r2, Range r3,
158 Range r4, Range r5, Range r6, Range r7, Range r8, Range r9, Range r10)
159{
160 reference(array);
161 slice(0, r0);
162 slice(1, r1);
163 slice(2, r2);
164 slice(3, r3);
165 slice(4, r4);
166 slice(5, r5);
167 slice(6, r6);
168 slice(7, r7);
169 slice(8, r8);
170 slice(9, r9);
171 slice(10, r10);
172}
173
174/*
175 * This member template is used to implement operator() with any
176 * combination of int and Range parameters. There's room for up
177 * to 11 parameters, but any unused parameters have no effect.
178 */
179template<class P_numtype, int N_rank> template<int N_rank2, class R0,
180 class R1, class R2, class R3, class R4, class R5, class R6, class R7,
181 class R8, class R9, class R10>
182void Array<P_numtype, N_rank>::constructSlice(Array<T_numtype, N_rank2>& array,
183 R0 r0, R1 r1, R2 r2, R3 r3, R4 r4, R5 r5, R6 r6, R7 r7, R8 r8, R9 r9,
184 R10 r10)
185{
186 MemoryBlockReference<P_numtype>::changeBlock(array, array.zeroOffset());
187 data_ = array.dataZero();
188
189 int setRank = 0;
190
191 TinyVector<int, N_rank2> rankMap;
192
193 slice(setRank, r0, array, rankMap, 0);
194 slice(setRank, r1, array, rankMap, 1);
195 slice(setRank, r2, array, rankMap, 2);
196 slice(setRank, r3, array, rankMap, 3);
197 slice(setRank, r4, array, rankMap, 4);
198 slice(setRank, r5, array, rankMap, 5);
199 slice(setRank, r6, array, rankMap, 6);
200 slice(setRank, r7, array, rankMap, 7);
201 slice(setRank, r8, array, rankMap, 8);
202 slice(setRank, r9, array, rankMap, 9);
203 slice(setRank, r10, array, rankMap, 10);
204
205 // Redo the ordering_ array to account for dimensions which
206 // have been sliced away.
207 int j = 0;
208 for (int i=0; i < N_rank2; ++i)
209 {
210 if (rankMap[array.ordering(i)] != -1)
211 storage_.setOrdering(j++, rankMap[array.ordering(i)]);
212 }
213
214 calculateZeroOffset();
215}
216
217/*
218 * This member template is also used in the implementation of
219 * operator() with any combination of int and Rank parameters.
220 * It's called by constructSlice(), above. This version handles
221 * Range parameters.
222 */
223template<class T_numtype, int N_rank> template<int N_rank2>
224void Array<T_numtype, N_rank>::slice(int& setRank, Range r,
225 Array<T_numtype,N_rank2>& array, TinyVector<int,N_rank2>& rankMap,
226 int sourceRank)
227{
228 // NEEDS WORK: ordering will change completely when some ranks
229 // are deleted.
230
231#ifdef BZ_DEBUG_SLICE
232cout << "slice(" << setRank << ", [" << r.first(array.lbound(sourceRank))
233 << ", " << r.last(array.ubound(sourceRank)) << "], Array<T,"
234 << N_rank2 << ">, " << sourceRank << ")" << endl;
235#endif
236
237 rankMap[sourceRank] = setRank;
238 length_[setRank] = array.length(sourceRank);
239 stride_[setRank] = array.stride(sourceRank);
240 storage_.setAscendingFlag(setRank, array.isRankStoredAscending(sourceRank));
241 storage_.setBase(setRank, array.base(sourceRank));
242 slice(setRank, r);
243 ++setRank;
244}
245
246/*
247 * This member template is also used in the implementation of
248 * operator() with any combination of int and Rank parameters.
249 * It's called by constructSlice(), above. This version handles
250 * int parameters, which reduce the dimensionality by one.
251 */
252template<class T_numtype, int N_rank> template<int N_rank2>
253void Array<T_numtype, N_rank>::slice(int& setRank, int i,
254 Array<T_numtype,N_rank2>& array, TinyVector<int,N_rank2>& rankMap,
255 int sourceRank)
256{
257#ifdef BZ_DEBUG_SLICE
258 cout << "slice(" << setRank << ", " << i
259 << ", Array<T," << N_rank2 << ">, " << sourceRank << ")" << endl;
260 cout << "Offset by " << (i * array.stride(sourceRank))
261 << endl;
262#endif
263 rankMap[sourceRank] = -1;
264 data_ += i * array.stride(sourceRank);
265#ifdef BZ_DEBUG_SLICE
266 cout << "data_ = " << data_ << endl;
267#endif
268}
269
270/*
271 * After calling slice(int rank, Range r), the array refers only to the
272 * Range r of the original array.
273 * e.g. Array<int,1> x(100);
274 * x.slice(firstRank, Range(25,50));
275 * x = 0; // Sets elements 25..50 of the original array to 0
276 */
277template<class P_numtype, int N_rank>
278void Array<P_numtype, N_rank>::slice(int rank, Range r)
279{
280 BZPRECONDITION((rank >= 0) && (rank < N_rank));
281
282 int first = r.first(lbound(rank));
283 int last = r.last(ubound(rank));
284 int stride = r.stride();
285
286#ifdef BZ_DEBUG_SLICE
287cout << "slice(" << rank << ", Range):" << endl
288 << "first = " << first << " last = " << last << "stride = " << stride
289 << endl << "length_[rank] = " << length_[rank] << endl;
290#endif
291
292 BZPRECHECK(
293 ((first <= last) && (stride > 0)
294 || (first >= last) && (stride < 0))
295 && (unsigned(first - base(rank)) < length_[rank])
296 && (unsigned(last - base(rank)) < length_[rank]),
297 "Bad array slice: Range(" << first << ", " << last << ", "
298 << stride << "). Array is Range(" << lbound(rank) << ", "
299 << ubound(rank) << ")");
300
301 // Will the storage be non-contiguous?
302 // (1) Slice in the minor dimension and the range does not span
303 // the entire index interval (NB: non-unit strides are possible)
304 // (2) Slice in a middle dimension and the range is not Range::all()
305
306 // Note: this code ignores a few weird cases that would hopefully come
307 // up rarely, e.g. slicing the array 0..99,0..99 with
308 // Range::all() and Range(1,99,2). This preserves contiguous
309 // storage, but the contiguousStorage_ flag will still be set
310 // false. This isn't a serious problem -- array operations will
311 // just be a tad slower in this situation.
312 if (isMinorRank(rank) &&
313 ((first != base(rank)) || (last != base(rank) + length_[rank] - 1)))
314 storageContiguous_ = _bz_false;
315
316 if ((ordering(rank) != N_rank-1) && (stride != 1))
317 storageContiguous_ = _bz_false;
318
319 length_[rank] = (last - first) / stride + 1;
320
321 int offset = (first - base(rank)) * stride_[rank];
322 data_ += offset;
323 zeroOffset_ -= offset;
324
325 stride_[rank] *= stride;
326}
327
328BZ_NAMESPACE_END
329
330#endif // BZ_ARRAYSLICING_CC
Note: See TracBrowser for help on using the repository browser.