source: XIOS/dev/dev_olga/src/extern/blitz/include/blitz/array/storage.h @ 1022

Last change on this file since 1022 was 1022, checked in by mhnguyen, 7 years ago
File size: 14.0 KB
Line 
1// -*- C++ -*-
2/***************************************************************************
3 * blitz/array/storage.h  Memory layout of Arrays.
4 *
5 * $Id$
6 *
7 * Copyright (C) 1997-2011 Todd Veldhuizen <tveldhui@acm.org>
8 *
9 * This file is a part of Blitz.
10 *
11 * Blitz is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation, either version 3
14 * of the License, or (at your option) any later version.
15 *
16 * Blitz is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with Blitz.  If not, see <http://www.gnu.org/licenses/>.
23 *
24 * Suggestions:          blitz-devel@lists.sourceforge.net
25 * Bugs:                 blitz-support@lists.sourceforge.net   
26 *
27 * For more information, please see the Blitz++ Home Page:
28 *    https://sourceforge.net/projects/blitz/
29 *
30 ****************************************************************************/
31#ifndef BZ_ARRAY_STORAGE_H
32#define BZ_ARRAY_STORAGE_H
33
34#ifdef BZ_HAVE_BOOST_SERIALIZATION
35#include <boost/serialization/serialization.hpp>
36#endif
37#ifdef BZ_HAVE_BOOST_MPI
38#include <boost/mpi/datatype.hpp>
39#endif
40
41BZ_NAMESPACE(blitz)
42
43
44/// Enum for specifying whether padding for alignment should be done.
45enum paddingPolicy {
46  /// The container should have contiguous data.
47  contiguousData,
48  /** The container data should be padded so minor rank dimensions
49      always are SIMD aligned. */
50  paddedData
51};
52
53
54/** The default padding policy, set by the configure script
55    --enable-array-length-padding argument. */
56const paddingPolicy defaultPadding = BZ_PADDING_DEFAULT;
57
58
59/**
60  Declaration of class GeneralArrayStorage<N_rank>
61 
62  This class describes a storage format for an N-dimensional array.
63  The dimensions can be stored in an arbitrary order (for example, as
64  a C-style row major array or Fortran-style column major array, or
65  something else entirely).  Each dimension can be stored in either
66  ascending (the most common) or descending order.  Each dimension can
67  have its own base (starting index value: e.g. 0 for C-style arrays,
68  1 for Fortran arrays).  The GeneralArrayStorage class also
69  determines the padding policy when SIMD width is set.
70
71  GeneralArrayStorage<N> defaults to C-style arrays.  To implement
72  other storage formats, subclass and modify the constructor.  The
73  class FortranArray, below, is an example.
74 
75  Objects inheriting from GeneralArrayStorage<N> can be passed as
76  an optional constructor argument to Array objects.
77  e.g. Array<int,3> A(16,16,16, FortranArray<3>());
78  will create a 3-dimensional 16x16x16 Fortran-style array.
79 */
80
81template<int N_rank>
82class GeneralArrayStorage {
83public:
84    class noInitializeFlag { };
85
86    GeneralArrayStorage(noInitializeFlag)
87    { }
88
89    GeneralArrayStorage(paddingPolicy pp = defaultPadding)
90    {
91        for (int i=0; i < N_rank; ++i)
92          ordering_(i) = N_rank - 1 - i;
93        ascendingFlag_ = true;
94        base_ = 0;
95        paddingPolicy_ = pp;
96    }
97
98    GeneralArrayStorage(const GeneralArrayStorage<N_rank>& x)
99      : paddingPolicy_(x.paddingPolicy_), ascendingFlag_(x.ascendingFlag_),
100        ordering_(x.ordering_), base_(x.base_)
101    { 
102    }
103
104    GeneralArrayStorage(TinyVector<int,N_rank> ordering,
105                        TinyVector<bool,N_rank> ascendingFlag,
106                        paddingPolicy pp = defaultPadding)
107      : paddingPolicy_(pp), ascendingFlag_(ascendingFlag),
108        ordering_(ordering)
109    {
110        base_ = 0;
111    }
112
113    ~GeneralArrayStorage()
114    { }
115
116    GeneralArrayStorage<N_rank>& operator=(
117        const GeneralArrayStorage<N_rank>& rhs)
118    {
119        ordering_ = rhs.ordering();
120        ascendingFlag_ = rhs.ascendingFlag();
121        base_ = rhs.base();
122        paddingPolicy_ = rhs.paddingPolicy_;
123        return *this;
124    }
125
126    TinyVector<int, N_rank>& ordering()
127    { return ordering_; }
128
129    const TinyVector<int, N_rank>& ordering() const
130    { return ordering_; }
131
132    int ordering(int i) const
133    { return ordering_[i]; }
134
135    void setOrdering(int i, int order) 
136    { ordering_[i] = order; }
137
138    bool allRanksStoredAscending() const
139    {
140        for (int i=0; i < N_rank; ++i)
141            if (!ascendingFlag_[i]) return false;
142        return true;
143    }
144
145    bool isRankStoredAscending(int i) const
146    { return ascendingFlag_[i]; }
147
148    TinyVector<bool, N_rank>& ascendingFlag() 
149    { return ascendingFlag_; }
150
151    const TinyVector<bool, N_rank>& ascendingFlag() const
152    { return ascendingFlag_; }
153
154    void setAscendingFlag(int i, bool ascendingFlag) 
155    { ascendingFlag_[i] = ascendingFlag; }
156
157    TinyVector<int, N_rank>& base()
158    { return base_; }
159
160    const TinyVector<int, N_rank>& base() const
161    { return base_; }
162
163    int base(int i) const
164    { return base_[i]; }
165
166    void setBase(int i, int base)
167    { base_[i] = base; }
168
169    void setBase(const TinyVector<int, N_rank>& base)
170    { base_ = base; }
171
172  const paddingPolicy& padding() const { return paddingPolicy_; }
173
174private:
175#ifdef BZ_HAVE_BOOST_SERIALIZATION
176  friend class boost::serialization::access;
177
178    template<class T_arch>
179    void serialize(T_arch& ar, const unsigned int version) {
180      ar & paddingPolicy_;
181      ar & ascendingFlag_;
182      ar & ordering_;
183      ar & base_;
184    };
185#endif
186
187protected:
188    /*
189     * ordering_[] specifies the order in which the array is stored in
190     * memory.  For a newly allocated array, ordering_(0) will give the
191     * rank with unit stride, and ordering_(N_rank-1) will be the rank
192     * with largest stride.  An order like [2, 1, 0] corresponds to
193     * C-style array storage; an order like [0, 1, 2] corresponds to
194     * Fortran array storage.
195     *
196     * ascendingFlag_[] indicates whether the data in a rank is stored
197     * in ascending or descending order.  Most of the time these values
198     * will all be true (indicating ascending order).  Some peculiar
199     * formats (e.g. MS-Windows BMP image format) store the data in
200     * descending order.
201     * 
202     * base_[] gives the first valid index for each rank.  For a C-style
203     * array, all the base_ elements will be zero; for a Fortran-style
204     * array, they will be one.  base_[] can be set arbitrarily using
205     * the Array constructor which takes a Range argument, e.g.
206     * Array<float,2> A(Range(30,40),Range(23,33));
207     * will create an array with base_[] = { 30, 23 }.
208     */
209
210    // declare the tinyvector<bool> first, because it doesn't have alignment
211    paddingPolicy paddingPolicy_;
212    TinyVector<bool, N_rank> ascendingFlag_;
213    TinyVector<int,  N_rank> ordering_;
214    TinyVector<int,  N_rank> base_;
215};
216
217
218/** This tag class can be used to provide a nicer notation for
219    constructing padded arrays: instead of
220      Array<int,2> A(3, 3, GeneralArrayStorage<2>(paddedData));
221    one can simply write:
222      Array<int,2> A(3, 3, paddedArray);
223    where paddedArray is an object of type _bz_paddedTag.
224*/
225class _bz_paddedTag {
226public:
227    operator GeneralArrayStorage<1>()
228    { return GeneralArrayStorage<1>(paddedData); }
229
230    operator GeneralArrayStorage<2>()
231    { return GeneralArrayStorage<2>(paddedData); }
232
233    operator GeneralArrayStorage<3>()
234    { return GeneralArrayStorage<3>(paddedData); }
235
236    operator GeneralArrayStorage<4>()
237    { return GeneralArrayStorage<4>(paddedData); }
238
239    operator GeneralArrayStorage<5>()
240    { return GeneralArrayStorage<5>(paddedData); }
241
242    operator GeneralArrayStorage<6>()
243    { return GeneralArrayStorage<6>(paddedData); }
244
245    operator GeneralArrayStorage<7>()
246    { return GeneralArrayStorage<7>(paddedData); }
247
248    operator GeneralArrayStorage<8>()
249    { return GeneralArrayStorage<8>(paddedData); }
250
251    operator GeneralArrayStorage<9>()
252    { return GeneralArrayStorage<9>(paddedData); }
253
254    operator GeneralArrayStorage<10>()
255    { return GeneralArrayStorage<10>(paddedData); }
256
257    operator GeneralArrayStorage<11>()
258    { return GeneralArrayStorage<11>(paddedData); }
259};
260
261// A global instance of this class will be placed in
262// the blitz library (libblitz.a on unix machines).
263
264_bz_global _bz_paddedTag paddedArray;
265
266
267/** This tag class can be used to provide a nicer notation for
268    constructing unpadded arrays: instead of
269      Array<int,2> A(3, 3, GeneralArrayStorage<2>(contiguousData));
270    one can simply write:
271      Array<int,2> A(3, 3, contiguousArray);
272    where contiguousArray is an object of type _bz_contiguousTag.
273*/
274class _bz_contiguousTag {
275public:
276    operator GeneralArrayStorage<1>()
277    { return GeneralArrayStorage<1>(contiguousData); }
278
279    operator GeneralArrayStorage<2>()
280    { return GeneralArrayStorage<2>(contiguousData); }
281
282    operator GeneralArrayStorage<3>()
283    { return GeneralArrayStorage<3>(contiguousData); }
284
285    operator GeneralArrayStorage<4>()
286    { return GeneralArrayStorage<4>(contiguousData); }
287
288    operator GeneralArrayStorage<5>()
289    { return GeneralArrayStorage<5>(contiguousData); }
290
291    operator GeneralArrayStorage<6>()
292    { return GeneralArrayStorage<6>(contiguousData); }
293
294    operator GeneralArrayStorage<7>()
295    { return GeneralArrayStorage<7>(contiguousData); }
296
297    operator GeneralArrayStorage<8>()
298    { return GeneralArrayStorage<8>(contiguousData); }
299
300    operator GeneralArrayStorage<9>()
301    { return GeneralArrayStorage<9>(contiguousData); }
302
303    operator GeneralArrayStorage<10>()
304    { return GeneralArrayStorage<10>(contiguousData); }
305
306    operator GeneralArrayStorage<11>()
307    { return GeneralArrayStorage<11>(contiguousData); }
308};
309
310// A global instance of this class will be placed in
311// the blitz library (libblitz.a on unix machines).
312
313_bz_global _bz_contiguousTag contiguousArray;
314
315
316/**
317   Class FortranArray specializes GeneralArrayStorage to provide
318   Fortran style arrays (column major ordering, base of 1).  The
319   noInitializeFlag() passed to the base constructor indicates that
320   the subclass will take care of initializing the ordering_,
321   ascendingFlag_ and base_ members.
322 */
323template<int N_rank>
324class FortranArray : public GeneralArrayStorage<N_rank> {
325private:
326    typedef GeneralArrayStorage<N_rank> T_base;
327    typedef _bz_typename T_base::noInitializeFlag noInitializeFlag;
328    using T_base::ordering_;
329    using T_base::ascendingFlag_;
330    using T_base::base_;
331    using T_base::paddingPolicy_;
332public:
333    FortranArray(paddingPolicy pp = defaultPadding)
334        : GeneralArrayStorage<N_rank>(noInitializeFlag())
335    {
336        for (int i=0; i < N_rank; ++i)
337          ordering_(i) = i;
338        ascendingFlag_ = true;
339        base_ = 1;
340        paddingPolicy_ = pp;
341    }
342};
343
344
345// This tag class can be used to provide a nicer notation for
346// constructing Fortran-style arrays: instead of
347//     Array<int,2> A(3, 3, FortranArray<2>());
348// one can simply write:
349//     Array<int,2> A(3, 3, fortranArray);
350// where fortranArray is an object of type _bz_fortranTag.
351
352class _bz_fortranTag {
353public:
354    operator GeneralArrayStorage<1>()
355    { return FortranArray<1>(); }
356
357    operator GeneralArrayStorage<2>()
358    { return FortranArray<2>(); }
359
360    operator GeneralArrayStorage<3>()
361    { return FortranArray<3>(); }
362
363    operator GeneralArrayStorage<4>()
364    { return FortranArray<4>(); }
365
366    operator GeneralArrayStorage<5>()
367    { return FortranArray<5>(); }
368
369    operator GeneralArrayStorage<6>()
370    { return FortranArray<6>(); }
371
372    operator GeneralArrayStorage<7>()
373    { return FortranArray<7>(); }
374
375    operator GeneralArrayStorage<8>()
376    { return FortranArray<8>(); }
377
378    operator GeneralArrayStorage<9>()
379    { return FortranArray<9>(); }
380
381    operator GeneralArrayStorage<10>()
382    { return FortranArray<10>(); }
383
384    operator GeneralArrayStorage<11>()
385    { return FortranArray<11>(); }
386};
387
388// A global instance of this class will be placed in
389// the blitz library (libblitz.a on unix machines).
390
391_bz_global _bz_fortranTag fortranArray;
392
393
394/**
395   Class ColumnMajorArray specializes GeneralArrayStorage to provide
396   column major arrays (column major ordering, base of 0).
397 */
398
399template<int N_rank>
400class ColumnMajorArray : public GeneralArrayStorage<N_rank> {
401private:
402    typedef GeneralArrayStorage<N_rank> T_base;
403    typedef _bz_typename T_base::noInitializeFlag noInitializeFlag;
404    using T_base::ordering_;
405    using T_base::ascendingFlag_;
406    using T_base::base_;
407    using T_base::paddingPolicy_;
408public:
409  ColumnMajorArray(paddingPolicy pp = defaultPadding)
410    : GeneralArrayStorage<N_rank>(noInitializeFlag())
411    {
412      ordering_ = tensor::i;//Range(0, N_rank - 1);
413        ascendingFlag_ = true;
414        base_ = 0;
415        paddingPolicy_ = pp;
416    }
417};
418
419// This tag class can be used to provide a nicer notation for
420// constructing column major arrays: instead of
421//     Array<int,2> A(3, 3, ColumnMajorArray<2>());
422// one can simply write:
423//     Array<int,2> A(3, 3, columnMajorArray);
424// where columnMajorArray is an object of type _bz_columnMajorTag.
425
426class _bz_columnMajorTag {
427
428public:
429    operator GeneralArrayStorage<1>()
430    { return ColumnMajorArray<1>(); }
431
432    operator GeneralArrayStorage<2>()
433    { return ColumnMajorArray<2>(); }
434
435    operator GeneralArrayStorage<3>()
436    { return ColumnMajorArray<3>(); }
437
438    operator GeneralArrayStorage<4>()
439    { return ColumnMajorArray<4>(); }
440
441    operator GeneralArrayStorage<5>()
442    { return ColumnMajorArray<5>(); }
443
444    operator GeneralArrayStorage<6>()
445    { return ColumnMajorArray<6>(); }
446
447    operator GeneralArrayStorage<7>()
448    { return ColumnMajorArray<7>(); }
449
450    operator GeneralArrayStorage<8>()
451    { return ColumnMajorArray<8>(); }
452
453    operator GeneralArrayStorage<9>()
454    { return ColumnMajorArray<9>(); }
455
456    operator GeneralArrayStorage<10>()
457    { return ColumnMajorArray<10>(); }
458
459    operator GeneralArrayStorage<11>()
460    { return ColumnMajorArray<11>(); }
461};
462
463// A global instance of this class will be placed in
464// the blitz library (libblitz.a on unix machines).
465
466_bz_global _bz_columnMajorTag columnMajorArray;
467
468
469BZ_NAMESPACE_END
470
471#ifdef BZ_HAVE_BOOST_MPI
472namespace boost { namespace mpi {
473  template <int N>
474  struct is_mpi_datatype<blitz::GeneralArrayStorage<N> > : boost::mpl::true_ { };
475} }
476#endif
477
478#endif // BZ_ARRAY_STORAGE_H
479
Note: See TracBrowser for help on using the repository browser.