strided.h 11.6 KB
Newer Older
1
2
3
4
5
/*! \file strided.h
 * \brief shape of s strided array (prototypes)
 * 
 * ----------------------------------------------------------------------------
 * 
thomas.forbriger's avatar
thomas.forbriger committed
6
 * $Id$
7
 * \author Thomas Forbriger
8
 * \since 08/12/2002
9
10
 * 
 * shape of s strided array (prototypes)
thomas.forbriger's avatar
thomas.forbriger committed
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 *
 * ----
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version. 
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 * ----
 *
28
29
30
31
32
 * \sa aff::Strided
 *
 * \note
 * You usually will not include this directly. It is included through array.h
 * and binarray.h
33
34
35
36
 * 
 * Copyright (c) 2002 by Thomas Forbriger (IMG Frankfurt) 
 * 
 * REVISIONS and CHANGES 
37
 *  - 08/12/2002   V1.0   copied from libcontxx
38
39
40
41
42
43
 *  - 11/12/2002   V1.1   revision of this part of code (thof)
 *                        - remove template parameter
 *                        - replace by maximum dimensionality constant
 *                        - does not need to know anything about stepper
 *                        - introduced Mbase (is necessary for new concept of
 *                          multidemensional arrays proposed by wolle)
thomas.forbriger's avatar
thomas.forbriger committed
44
45
46
 *  - 12/12/2002   V1.2   (thof)
 *                        - basic functionality is complete
 *                        - documentation is still missing
thomas.forbriger's avatar
thomas.forbriger committed
47
48
 *  - 13/12/2002   V1.3   (thof)
 *                        - correct definition of mapping formula
thomas.forbriger's avatar
thomas.forbriger committed
49
50
 *                        - provides enough basic functionality 
 *                          (including access needed by stepper)
51
52
53
 *  - 14/12/2002   V1.4   (thof)
 *                        - template-free definition part will now always
 *                          be placed in the binary library
thomas.forbriger's avatar
thomas.forbriger committed
54
55
56
 *  - 16/12/2002   V1.5   (thof)
 *                        - renamed subarray and slice function
 *                        - added shift and setfirst
thomas.forbriger's avatar
thomas.forbriger committed
57
58
59
 *  - 20/12/2002   V1.6   (thof)
 *                        - forward declaration of StridedStepper
 *                        - typedef Tstepper
60
61
 *  - 29/12/2002   V1.7   (thof)
 *                        - now provides basic Fortran style constructor
62
63
 *  - 15/05/2011   V1.8   (thof)
 *                        - added dense 1D array check
64
65
66
67
68
 * 
 * ============================================================================
 */

// include guard
69
#ifndef AFF_STRIDED_H_VERSION
70

71
#define AFF_STRIDED_H_VERSION \
72
  "AFF_STRIDED_H   V1.8"
73
#define AFF_STRIDED_H_CVSID \
thomas.forbriger's avatar
thomas.forbriger committed
74
  "$Id$"
75

76
77
#include<aff/lib/types.h>
#include<aff/lib/simplearray.h>
78

79
namespace aff {
80

thomas.forbriger's avatar
thomas.forbriger committed
81
82
83
84
85
  namespace util {
    //! forward declaration of stepper class
    class StridedStepper;
  } // namespace util

86
87
88
89
90
91
  /*! \brief Shape for a rectangular array layout.
   *
   * A rectangular array layout is the usual layout for multi-dimensional
   * arrays. This is in contrast to packed layouts for banded matrices or
   * triangular matrices that do not hold every array element.
   *
92
93
   * A Strided shape typically is constrcuted through an aff::Shaper class.
   *
94
95
96
97
98
99
100
   * \note
   * dimension index is 0,1,2,... (zero-based) when calling size(i) member
   * function e.g.
   *
   * \todo 
   * rework documentation of Strided
   *
thomas.forbriger's avatar
thomas.forbriger committed
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
   * \internal
   * \par Mapping of index values into linear representation range
   * The shape class defines how index values \a i0, \a i1, etc. are mapped
   * into the linear adressing range used by the memory representation (see
   * SharedHeap).
   * The adress in the linear array is
   * \f[
   * a=o+\sum\limits_{k=0}^{M-1}\;(i_k-f_k)\,s_k
   *  =\sum\limits_{k=0}^{M-1}\;i_k\,s_k+
   *   \underbrace{o-\sum_{k=0}^{M-1}f_k\,s_k}_{=b_{M-1}},
   * \f]
   * if \a M is the number of index values \f$ i_k \f$ passed to the access
   * operator. In formula \f$ f_k \f$ are the elements of \c Mfirst,
   * \f$ s_k \f$ are the elements of \c Mstride,
   * \f$ b_l \f$ are the elements of \c Mbase, and
thomas.forbriger's avatar
thomas.forbriger committed
116
   * \f$ o \f$ is \c Mbase[0] (i.e. the first accessible position within the
thomas.forbriger's avatar
thomas.forbriger committed
117
118
   * representation.
   *
119
   */
120
121
  class Strided {
    public:
thomas.forbriger's avatar
thomas.forbriger committed
122
123
124
125
      /*! maximum dimensionality
       * \note
       * Some parts of the code rely on \c Mmax_dimen>=2.
       */
126
127
128
129
130
131
      static const Tdim Mmax_dimen=4;
        
      //! type of size and stride array (always positive)
      typedef SimpleRigidArray<Tsize, Mmax_dimen> TSizeVec;
      //! type of limit arrays (any sign)
      typedef SimpleRigidArray<Tsubscript, Mmax_dimen> TIndexVec;
thomas.forbriger's avatar
thomas.forbriger committed
132
133
      //! type of stepper
      typedef aff::util::StridedStepper Tstepper;
134

thomas.forbriger's avatar
thomas.forbriger committed
135
136
137
138
139
      /*-----------------------------------------------------------------*/

      /*! \name Constructors
       */
      //@{
140
      //! construct and initialize to zero
thomas.forbriger's avatar
thomas.forbriger committed
141
      Strided(): Mstride(0), Mfirst(0), Mlast(0), Mbase(0) { }
142
143
144
145
146
147
148
      /*! \brief construct do given size and first index
       *
       * \param sizes vector defining index range size for each dimension
       * \param first defines first index for each dimension
       * \param shift defines offset shift (i.e. first element accessed in
       *              memory representation)
       */
149
      explicit Strided(const TSizeVec& sizes, const Tsubscript& first=1,
150
151
              const Tsubscript& shift=0)
      { setup_from_size(sizes, first, shift); }
152
      /*! \brief construct Fortran layout to given first and last index
153
154
155
156
157
       *
       * \param first vector of first index value in each dimension
       * \param last vector of last index value in each dimension
       * \param shift defines offset shift (i.e. first element accessed in
       *              memory representation)
158
159
160
161
       *
       * This constructor together with the aff::Strided::shrink() function is
       * used by aff::Shaper in aff::Shaper::operator Tshape () to create a
       * strided shape.
162
       * \sa \ref page_array_layout
163
       */
164
      explicit Strided(const TIndexVec& first, const TIndexVec& last, 
165
              const Tsubscript& shift=0);
166
167
168
169
170
171
      /*! \brief construct from given set of Fortran style sizes
       *
       * \param s0 size of first dimension
       * \param s1 size of second dimension
       * \param s2 size of third dimension
       * \param s3 size of fourth dimension
172
173
       *
       * \sa \ref page_array_layout
174
       */
175
      explicit Strided(const Tsize& s0, const Tsize& s1=1, 
176
              const Tsize& s2=1, const Tsize& s3=1);
thomas.forbriger's avatar
thomas.forbriger committed
177
178
179
      //@}

      /*-----------------------------------------------------------------*/
thomas.forbriger's avatar
thomas.forbriger committed
180
181

      /*! \name Access to shape
182
183
       *
       */
thomas.forbriger's avatar
thomas.forbriger committed
184
      //@{
185
186
187
188
      //! total size of mapped memory range
      Tsize memory_size() const
      { return (offset(Mlast)-offset(Mfirst)+1); }
      //! total number of mapped elements
thomas.forbriger's avatar
thomas.forbriger committed
189
190
      Tsize size() const;
      //! first mapped position
thomas.forbriger's avatar
thomas.forbriger committed
191
      Tsubscript first_offset() const
thomas.forbriger's avatar
thomas.forbriger committed
192
193
      { return offset(Mfirst[0]); }
      //! last mapped position
thomas.forbriger's avatar
thomas.forbriger committed
194
      Tsubscript last_offset() const
thomas.forbriger's avatar
thomas.forbriger committed
195
      { return offset(Mlast); }
196
197
198
199
      //! first index of dimension \par i
      const Tsubscript& first(const Tsubscript& i) const
      { return Mfirst[i]; }
      //! last index of dimension \par i
thomas.forbriger's avatar
thomas.forbriger committed
200
      const Tsubscript& last(const Tsubscript& i) const
thomas.forbriger's avatar
thomas.forbriger committed
201
      { return (Mlast[i]); }
202
      //! size of dimension \par i
thomas.forbriger's avatar
thomas.forbriger committed
203
      Tsize size(const Tsubscript& i) const
thomas.forbriger's avatar
thomas.forbriger committed
204
      { return (static_cast<Tsize>(Mlast[i]-Mfirst[i]+1)); }
205
206
207
      //! stride of dimension \par i
      const Tsize& stride(const Tsubscript& i) const
      { return Mstride[i]; }
thomas.forbriger's avatar
thomas.forbriger committed
208
209
210
211
212
213
      //! return vector of first index values
      const TIndexVec& first() const { return(Mfirst); }
      //! return vector of last index values
      const TIndexVec& last() const { return(Mlast); }
      //! return vector of stride values
      const TSizeVec& stride() const { return(Mstride); }
thomas.forbriger's avatar
thomas.forbriger committed
214
      //@}
215

thomas.forbriger's avatar
thomas.forbriger committed
216
217
      /*-----------------------------------------------------------------*/

thomas.forbriger's avatar
thomas.forbriger committed
218
219
220
221
      /*! \name Map index values to linear representation range
       *
       */
      //@{
222
      //! full dimensionality access
thomas.forbriger's avatar
thomas.forbriger committed
223
224
      Tsubscript offset(const TIndexVec& index) const
      { return(inline_innerproduct(index,Mstride)+Mbase[Mmax_dimen-1]); }
225
      //! offset from 1 index value
thomas.forbriger's avatar
thomas.forbriger committed
226
      Tsubscript offset(const Tsubscript& i0) const
thomas.forbriger's avatar
thomas.forbriger committed
227
      { return(i0*Mstride[0]+Mbase[0]); }
228
      //! offset from 2 index values
thomas.forbriger's avatar
thomas.forbriger committed
229
230
      Tsubscript offset(const Tsubscript& i0,
                        const Tsubscript& i1) const
thomas.forbriger's avatar
thomas.forbriger committed
231
      { return(i0*Mstride[0]+i1*Mstride[1]+Mbase[1]); }
232
      //! offset from 3 index values
thomas.forbriger's avatar
thomas.forbriger committed
233
234
235
      Tsubscript offset(const Tsubscript& i0,
                        const Tsubscript& i1,
                        const Tsubscript& i2) const
thomas.forbriger's avatar
thomas.forbriger committed
236
      { return(i0*Mstride[0]+i1*Mstride[1]+i2*Mstride[2]+Mbase[2]); }
237
      //! offset from 4 index values
thomas.forbriger's avatar
thomas.forbriger committed
238
239
240
241
      Tsubscript offset(const Tsubscript& i0,
                        const Tsubscript& i1,
                        const Tsubscript& i2,
                        const Tsubscript& i3) const
thomas.forbriger's avatar
thomas.forbriger committed
242
243
244
245
      { return(i0*Mstride[0]+i1*Mstride[1]+i2*Mstride[2]+
               i3*Mstride[3]+Mbase[3]); }
      //@}

thomas.forbriger's avatar
thomas.forbriger committed
246
247
      /*-----------------------------------------------------------------*/

thomas.forbriger's avatar
thomas.forbriger committed
248
249
      /*! \name Support for slices and subarrays
       *
thomas.forbriger's avatar
thomas.forbriger committed
250
251
252
253
254
255
256
       * \note 
       * We intentionally call the subarray and slice functions \c shrink and
       * \c collapse (rather than \c subarray and \c slice), because they do
       * not return another shape instance, which is a subarray or slice. They
       * in fact manipulate the existing instance and return itself! To get a
       * copy, you must first create a copy and then call shrink, collapse,
       * shift or setfirst for this copy.
thomas.forbriger's avatar
thomas.forbriger committed
257
258
       */
      //@{
thomas.forbriger's avatar
thomas.forbriger committed
259
      //! subarray
thomas.forbriger's avatar
thomas.forbriger committed
260
      Strided& shrink(const TIndexVec& last);
thomas.forbriger's avatar
thomas.forbriger committed
261
      //! subarray
thomas.forbriger's avatar
thomas.forbriger committed
262
      Strided& shrink(const TIndexVec& first, const TIndexVec& last);
thomas.forbriger's avatar
thomas.forbriger committed
263
      //! subarray
thomas.forbriger's avatar
thomas.forbriger committed
264
265
      Strided& shrink(const Tdim& i, 
                      const Tsubscript& first, const Tsubscript& last);
thomas.forbriger's avatar
thomas.forbriger committed
266
      //! subarray
thomas.forbriger's avatar
thomas.forbriger committed
267
268
      Strided& shrink(const Tdim& i, 
                      const Tsubscript& last);
thomas.forbriger's avatar
thomas.forbriger committed
269
      //! slice
thomas.forbriger's avatar
thomas.forbriger committed
270
      Strided& collapse(const Tdim& i, const Tsubscript& index);
thomas.forbriger's avatar
thomas.forbriger committed
271
272
273
274
275
276
277
278
      //! shift
      Strided& shift(const Tdim& i, const Tsubscript& index);
      //! shift
      Strided& shift(const TIndexVec& index);
      //! setfirst
      Strided& setfirst(const Tdim& i, const Tsubscript& index);
      //! setfirst
      Strided& setfirst(const TIndexVec& index);
thomas.forbriger's avatar
thomas.forbriger committed
279
      //@}
280

thomas.forbriger's avatar
thomas.forbriger committed
281
282
      /*-----------------------------------------------------------------*/

283
    private:
thomas.forbriger's avatar
thomas.forbriger committed
284
      void calculate_base(const Tsubscript& offset);
285
286
287
      void setup_from_size(const TSizeVec& size, 
                           const Tsubscript& first=1,
                           const Tsubscript& shift=0);
288
289
290

      TSizeVec Mstride;   //<! strides for each dimension
      TIndexVec Mfirst;   //<! first index of each dimension
thomas.forbriger's avatar
thomas.forbriger committed
291
      TIndexVec Mlast;    //<! last index of each dimension
292
293
      TIndexVec Mbase;    //<! base for each dimension (see index operators)
  };
294

295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
  /*======================================================================*/
  // helper functions
  
  namespace util {

    /*! \brief check whether array shape describes a 1D array with dense
     * layout in the memory.
     *
     * \ingroup group_array_extensions
     * \param shape array shape
     * \return true if shape is dense and 1D
     */
    bool is_dense_1D_array(const aff::Strided& shape);

  } // namespace util

311
} // namespace aff
312

313
#endif // AFF_STRIDED_H_VERSION (includeguard)
314
315

/* ----- END OF strided.h ----- */