1 | /*
|
---|
2 | * $Id: methods.cc,v 1.1.1.1 1999-11-26 16:37:07 ansari Exp $
|
---|
3 | *
|
---|
4 | * $Log: not supported by cvs2svn $
|
---|
5 | // Revision 1.1.1.1 1999/04/09 17:59:03 ansari
|
---|
6 | // Creation module DPC/Blitz (blitz 0.4) Reza 09/04/99
|
---|
7 | //
|
---|
8 | * Revision 1.4 1998/03/14 00:04:47 tveldhui
|
---|
9 | * 0.2-alpha-05
|
---|
10 | *
|
---|
11 | * Revision 1.3 1997/08/18 19:13:08 tveldhui
|
---|
12 | * Just prior to implementing fastRead() optimization for array
|
---|
13 | * expression evaluation.
|
---|
14 | *
|
---|
15 | * Revision 1.2 1997/08/15 21:14:10 tveldhui
|
---|
16 | * Just prior to loop-collapse change
|
---|
17 | *
|
---|
18 | */
|
---|
19 |
|
---|
20 | #ifndef BZ_ARRAYMETHODS_CC
|
---|
21 | #define BZ_ARRAYMETHODS_CC
|
---|
22 |
|
---|
23 | #ifndef BZ_ARRAY_H
|
---|
24 | #error <blitz/array/methods.cc> must be included via <blitz/array.h>
|
---|
25 | #endif
|
---|
26 |
|
---|
27 | #include <blitz/minmax.h> // Needed for resizeAndPreserve()
|
---|
28 |
|
---|
29 | BZ_NAMESPACE(blitz)
|
---|
30 |
|
---|
31 | template<class P_numtype, int N_rank> template<class T_expr>
|
---|
32 | Array<P_numtype,N_rank>::Array(_bz_ArrayExpr<T_expr> expr)
|
---|
33 | {
|
---|
34 | BZ_NOT_IMPLEMENTED();
|
---|
35 |
|
---|
36 | // Obtain storage order from an operand in the expression
|
---|
37 | // (if possible). Probably best to assume C-style storage,
|
---|
38 | // then pass the storage object to the expression for possible
|
---|
39 | // modification.
|
---|
40 |
|
---|
41 | // Obtain ubounds/lbounds from array operands. Precondition
|
---|
42 | // failure if any bounds missing.
|
---|
43 |
|
---|
44 | // Size array.
|
---|
45 |
|
---|
46 | // assignment of expression.
|
---|
47 | }
|
---|
48 |
|
---|
49 | template<class T_numtype, int N_rank>
|
---|
50 | Array<T_numtype,N_rank>::Array(const TinyVector<int, N_rank>& lbounds,
|
---|
51 | const TinyVector<int, N_rank>& extent,
|
---|
52 | const GeneralArrayStorage<N_rank>& storage)
|
---|
53 | : storage_(storage)
|
---|
54 | {
|
---|
55 | length_ = extent;
|
---|
56 | storage_.setBase(lbounds);
|
---|
57 | setupStorage(N_rank - 1);
|
---|
58 | }
|
---|
59 |
|
---|
60 |
|
---|
61 | /*
|
---|
62 | * This routine takes the storage information for the array
|
---|
63 | * (ascendingFlag_[], base_[], and ordering_[]) and the size
|
---|
64 | * of the array (length_[]) and computes the stride vector
|
---|
65 | * (stride_[]) and the zero offset (see explanation in array.h).
|
---|
66 | */
|
---|
67 | template<class P_numtype, int N_rank>
|
---|
68 | _bz_inline2 void Array<P_numtype, N_rank>::computeStrides()
|
---|
69 | {
|
---|
70 | if (N_rank > 1)
|
---|
71 | {
|
---|
72 | int stride = 1;
|
---|
73 |
|
---|
74 | // This flag simplifies the code in the loop, encouraging
|
---|
75 | // compile-time computation of strides through constant folding.
|
---|
76 | _bz_bool allAscending = storage_.allRanksStoredAscending();
|
---|
77 |
|
---|
78 | // BZ_OLD_FOR_SCOPING
|
---|
79 | int n;
|
---|
80 | for (n=0; n < N_rank; ++n)
|
---|
81 | {
|
---|
82 | int strideSign = +1;
|
---|
83 |
|
---|
84 | // If this rank is stored in descending order, then the stride
|
---|
85 | // will be negative.
|
---|
86 | if (!allAscending)
|
---|
87 | {
|
---|
88 | if (!isRankStoredAscending(ordering(n)))
|
---|
89 | strideSign = -1;
|
---|
90 | }
|
---|
91 |
|
---|
92 | // The stride for this rank is the product of the lengths of
|
---|
93 | // the ranks minor to it.
|
---|
94 | stride_[ordering(n)] = stride * strideSign;
|
---|
95 |
|
---|
96 | stride *= length_[ordering(n)];
|
---|
97 | }
|
---|
98 | }
|
---|
99 | else {
|
---|
100 | // Specialization for N_rank == 1
|
---|
101 | // This simpler calculation makes it easier for the compiler
|
---|
102 | // to propagate stride values.
|
---|
103 |
|
---|
104 | if (isRankStoredAscending(0))
|
---|
105 | stride_[0] = 1;
|
---|
106 | else
|
---|
107 | stride_[0] = -1;
|
---|
108 | }
|
---|
109 |
|
---|
110 | calculateZeroOffset();
|
---|
111 | }
|
---|
112 |
|
---|
113 | template<class T_numtype, int N_rank>
|
---|
114 | void Array<T_numtype, N_rank>::calculateZeroOffset()
|
---|
115 | {
|
---|
116 | // Calculate the offset of (0,0,...,0)
|
---|
117 | zeroOffset_ = 0;
|
---|
118 |
|
---|
119 | // zeroOffset_ = - sum(where(ascendingFlag_, stride_ * base_,
|
---|
120 | // (length_ - 1 + base_) * stride_))
|
---|
121 | for (int n=0; n < N_rank; ++n)
|
---|
122 | {
|
---|
123 | if (!isRankStoredAscending(n))
|
---|
124 | zeroOffset_ -= (length_[n] - 1 + base(n)) * stride_[n];
|
---|
125 | else
|
---|
126 | zeroOffset_ -= stride_[n] * base(n);
|
---|
127 | }
|
---|
128 | }
|
---|
129 |
|
---|
130 |
|
---|
131 |
|
---|
132 | template<class P_numtype, int N_rank>
|
---|
133 | void Array<P_numtype, N_rank>::dumpStructureInformation(ostream& os) const
|
---|
134 | {
|
---|
135 | os << "Dump of Array<" << BZ_DEBUG_TEMPLATE_AS_STRING_LITERAL(P_numtype)
|
---|
136 | << ", " << N_rank << ">:" << endl
|
---|
137 | << "ordering_ = " << storage_.ordering() << endl
|
---|
138 | << "ascendingFlag_ = " << storage_.ascendingFlag() << endl
|
---|
139 | << "base_ = " << storage_.base() << endl
|
---|
140 | << "length_ = " << length_ << endl
|
---|
141 | << "stride_ = " << stride_ << endl
|
---|
142 | << "zeroOffset_ = " << zeroOffset_ << endl
|
---|
143 | << "numElements() = " << numElements() << endl
|
---|
144 | << "storageContiguous = " << storageContiguous_ << endl;
|
---|
145 | }
|
---|
146 |
|
---|
147 | /*
|
---|
148 | * Make this array a view of another array's data.
|
---|
149 | */
|
---|
150 | template<class P_numtype, int N_rank>
|
---|
151 | void Array<P_numtype, N_rank>::reference(Array<P_numtype, N_rank>& array)
|
---|
152 | {
|
---|
153 | storage_ = array.storage_;
|
---|
154 | length_ = array.length_;
|
---|
155 | stride_ = array.stride_;
|
---|
156 | zeroOffset_ = array.zeroOffset_;
|
---|
157 | storageContiguous_ = array.storageContiguous_;
|
---|
158 |
|
---|
159 | MemoryBlockReference<P_numtype>::changeBlock(array, array.zeroOffset_);
|
---|
160 |
|
---|
161 | data_ = array.data_;
|
---|
162 | }
|
---|
163 |
|
---|
164 | /*
|
---|
165 | * This method is called to allocate memory for a new array.
|
---|
166 | */
|
---|
167 | template<class P_numtype, int N_rank>
|
---|
168 | _bz_inline2 void Array<P_numtype, N_rank>::setupStorage(int lastRankInitialized)
|
---|
169 | {
|
---|
170 | TAU_TYPE_STRING(p1, "Array<T,N>::setupStorage() [T="
|
---|
171 | + CT(P_numtype) + ",N=" + CT(N_rank) + "]");
|
---|
172 | TAU_PROFILE(" ", p1, TAU_BLITZ);
|
---|
173 |
|
---|
174 | /*
|
---|
175 | * If the length of some of the ranks was unspecified, fill these
|
---|
176 | * in using the last specified value.
|
---|
177 | *
|
---|
178 | * e.g. Array<int,3> A(40) results in a 40x40x40 array.
|
---|
179 | */
|
---|
180 | for (int i=lastRankInitialized + 1; i < N_rank; ++i)
|
---|
181 | {
|
---|
182 | storage_.setBase(i, storage_.base(lastRankInitialized));
|
---|
183 | length_[i] = length_[lastRankInitialized];
|
---|
184 | }
|
---|
185 |
|
---|
186 | // Compute strides
|
---|
187 | computeStrides();
|
---|
188 |
|
---|
189 | // Allocate a block of memory
|
---|
190 | MemoryBlockReference<P_numtype>::newBlock(numElements());
|
---|
191 |
|
---|
192 | // Adjust the base of the array to account for non-zero base
|
---|
193 | // indices and reversals
|
---|
194 | data_ += zeroOffset_;
|
---|
195 |
|
---|
196 | // A new array will always have contiguous storage
|
---|
197 | storageContiguous_ = _bz_true;
|
---|
198 | }
|
---|
199 |
|
---|
200 | template<class T_numtype, int N_rank>
|
---|
201 | Array<T_numtype, N_rank> Array<T_numtype, N_rank>::copy() const
|
---|
202 | {
|
---|
203 | if (numElements())
|
---|
204 | {
|
---|
205 | Array<T_numtype, N_rank> z(length_, storage_);
|
---|
206 | z = *this;
|
---|
207 | return z;
|
---|
208 | }
|
---|
209 | else {
|
---|
210 | // Null array-- don't bother allocating an empty block.
|
---|
211 | return *this;
|
---|
212 | }
|
---|
213 | }
|
---|
214 |
|
---|
215 | template<class T_numtype, int N_rank>
|
---|
216 | void Array<T_numtype, N_rank>::makeUnique()
|
---|
217 | {
|
---|
218 | if (numReferences() > 1)
|
---|
219 | {
|
---|
220 | T_array tmp = copy();
|
---|
221 | reference(tmp);
|
---|
222 | }
|
---|
223 | }
|
---|
224 |
|
---|
225 | template<class T_numtype, int N_rank>
|
---|
226 | Array<T_numtype, N_rank> Array<T_numtype, N_rank>::transpose(int r0, int r1,
|
---|
227 | int r2, int r3, int r4, int r5, int r6, int r7, int r8, int r9, int r10)
|
---|
228 | {
|
---|
229 | T_array B(*this);
|
---|
230 | B.transposeSelf(r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10);
|
---|
231 | return B;
|
---|
232 | }
|
---|
233 |
|
---|
234 | template<class T_numtype, int N_rank>
|
---|
235 | void Array<T_numtype, N_rank>::transposeSelf(int r0, int r1, int r2, int r3,
|
---|
236 | int r4, int r5, int r6, int r7, int r8, int r9, int r10)
|
---|
237 | {
|
---|
238 | BZPRECHECK(r0+r1+r2+r3+r4+r5+r6+r7+r8+r9+r10 == N_rank * (N_rank-1) / 2,
|
---|
239 | "Invalid array transpose() arguments." << endl
|
---|
240 | << "Arguments must be a permutation of the numerals (0,...,"
|
---|
241 | << (N_rank - 1) << ")");
|
---|
242 |
|
---|
243 | // Create a temporary reference copy of this array
|
---|
244 | Array<T_numtype, N_rank> x(*this);
|
---|
245 |
|
---|
246 | // Now reorder the dimensions using the supplied permutation
|
---|
247 | doTranspose(0, r0, x);
|
---|
248 | doTranspose(1, r1, x);
|
---|
249 | doTranspose(2, r2, x);
|
---|
250 | doTranspose(3, r3, x);
|
---|
251 | doTranspose(4, r4, x);
|
---|
252 | doTranspose(5, r5, x);
|
---|
253 | doTranspose(6, r6, x);
|
---|
254 | doTranspose(7, r7, x);
|
---|
255 | doTranspose(8, r8, x);
|
---|
256 | doTranspose(9, r9, x);
|
---|
257 | doTranspose(10, r10, x);
|
---|
258 | }
|
---|
259 |
|
---|
260 | template<class T_numtype, int N_rank>
|
---|
261 | void Array<T_numtype, N_rank>::doTranspose(int destRank, int sourceRank,
|
---|
262 | Array<T_numtype, N_rank>& array)
|
---|
263 | {
|
---|
264 | // BZ_NEEDS_WORK: precondition check
|
---|
265 |
|
---|
266 | if (destRank >= N_rank)
|
---|
267 | return;
|
---|
268 |
|
---|
269 | length_[destRank] = array.length_[sourceRank];
|
---|
270 | stride_[destRank] = array.stride_[sourceRank];
|
---|
271 | storage_.setAscendingFlag(destRank,
|
---|
272 | array.isRankStoredAscending(sourceRank));
|
---|
273 | storage_.setBase(destRank, array.base(sourceRank));
|
---|
274 |
|
---|
275 | // BZ_NEEDS_WORK: Handling the storage ordering is currently O(N^2)
|
---|
276 | // but it can be done fairly easily in linear time by constructing
|
---|
277 | // the appropriate permutation.
|
---|
278 |
|
---|
279 | // Find sourceRank in array.storage_.ordering_
|
---|
280 | int i=0;
|
---|
281 | for (; i < N_rank; ++i)
|
---|
282 | if (array.storage_.ordering(i) == sourceRank)
|
---|
283 | break;
|
---|
284 |
|
---|
285 | storage_.setOrdering(i, destRank);
|
---|
286 | }
|
---|
287 |
|
---|
288 | template<class T_numtype, int N_rank>
|
---|
289 | void Array<T_numtype, N_rank>::reverseSelf(int rank)
|
---|
290 | {
|
---|
291 | BZPRECONDITION(rank < N_rank);
|
---|
292 |
|
---|
293 | storage_.setAscendingFlag(rank, !isRankStoredAscending(rank));
|
---|
294 |
|
---|
295 | int adjustment = stride_[rank] * (length_[rank] - 1);
|
---|
296 | zeroOffset_ += adjustment;
|
---|
297 | data_ += adjustment;
|
---|
298 | stride_[rank] *= -1;
|
---|
299 | }
|
---|
300 |
|
---|
301 | template<class T_numtype, int N_rank>
|
---|
302 | Array<T_numtype, N_rank> Array<T_numtype,N_rank>::reverse(int rank)
|
---|
303 | {
|
---|
304 | T_array B(*this);
|
---|
305 | B.reverseSelf(rank);
|
---|
306 | return B;
|
---|
307 | }
|
---|
308 |
|
---|
309 | template<class T_numtype, int N_rank> template<class T_numtype2>
|
---|
310 | Array<T_numtype2,N_rank> Array<T_numtype,N_rank>::extractComponent(T_numtype2,
|
---|
311 | int componentNumber, int numComponents)
|
---|
312 | {
|
---|
313 | BZPRECONDITION((componentNumber >= 0) && (componentNumber < numComponents));
|
---|
314 |
|
---|
315 | TinyVector<int,N_rank> stride2;
|
---|
316 | stride2 = stride_ * numComponents;
|
---|
317 | T_numtype2* dataFirst2 = ((T_numtype2*)dataFirst()) + componentNumber;
|
---|
318 | return Array<T_numtype2,N_rank>(dataFirst2, length_, stride2, storage_);
|
---|
319 | }
|
---|
320 |
|
---|
321 | BZ_NAMESPACE_END
|
---|
322 |
|
---|
323 | #endif // BZ_ARRAY_CC
|
---|
324 |
|
---|