source: Sophya/trunk/SophyaExt/Blitz/blitz/array/methods.cc@ 221

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

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

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