blitz Version 0.10
blitz/array-impl.h
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 /***************************************************************************
00003  * blitz/array-impl.h    Definition of the Array<P_numtype, N_rank> class
00004  *
00005  * $Id: array-impl.h,v 1.33 2011/03/25 22:41:16 julianc Exp $
00006  *
00007  * Copyright (C) 1997-2011 Todd Veldhuizen <tveldhui@acm.org>
00008  *
00009  * This file is a part of Blitz.
00010  *
00011  * Blitz is free software: you can redistribute it and/or modify 
00012  * it under the terms of the GNU Lesser General Public License
00013  * as published by the Free Software Foundation, either version 3
00014  * of the License, or (at your option) any later version.
00015  *
00016  * Blitz is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU Lesser General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU Lesser General Public 
00022  * License along with Blitz.  If not, see <http://www.gnu.org/licenses/>.
00023  * 
00024  * Suggestions:          blitz-devel@lists.sourceforge.net
00025  * Bugs:                 blitz-support@lists.sourceforge.net    
00026  *
00027  * For more information, please see the Blitz++ Home Page:
00028  *    https://sourceforge.net/projects/blitz/
00029  *
00030  ***************************************************************************/
00031 
00032 /*
00033  * Wish list for array classes.
00034  *  - Arrays whose dimensions are unknown at compile time.
00035  *  - where()/elsewhere()/elsewhere() as in Dan Quinlan's implementation
00036  *  - block reduction operations
00037  *  - conversion to/from matrix & vector
00038  *  - apply(T func(T))
00039  *  - apply(T func(const T&))
00040  *  - apply<T func(T)>
00041  */
00042 
00043 #ifndef BZ_ARRAY_H
00044 #define BZ_ARRAY_H
00045 
00046 #include <blitz/blitz.h>
00047 #include <blitz/memblock.h>
00048 #include <blitz/range.h>
00049 #include <blitz/tinyvec.h>
00050 
00051 #ifdef BZ_ARRAY_SPACE_FILLING_TRAVERSAL
00052 #include <blitz/traversal.h>
00053 #endif
00054 
00055 #include <blitz/indexexpr.h>
00056 #include <blitz/prettyprint.h>
00057 
00058 #include <blitz/array/slice.h>     // Subarrays and slicing
00059 #include <blitz/array/map.h>       // Tensor index notation
00060 #include <blitz/array/multi.h>     // Multicomponent arrays
00061 #include <blitz/array/domain.h>    // RectDomain class
00062 #include <blitz/array/storage.h>   // GeneralArrayStorage
00063 
00064 
00065 BZ_NAMESPACE(blitz)
00066 
00067 /*
00068  * Forward declarations
00069  */
00070 
00071 template<typename T_numtype, int N_rank>
00072 class ArrayIterator;
00073 
00074 template<typename T_numtype, int N_rank>
00075 class ConstArrayIterator;
00076 
00077 template<typename T_numtype, int N_rank>
00078 class FastArrayIterator;
00079 
00080 template<typename P_expr>
00081 class _bz_ArrayExpr;
00082 
00083 template<typename T_array, typename T_index>
00084 class IndirectArray;
00085 
00086 template <typename P_numtype,int N_rank>
00087 void swap(Array<P_numtype,N_rank>&,Array<P_numtype,N_rank>&);
00088 
00089 template <typename P_numtype, int N_rank>
00090 void find(Array<TinyVector<int,N_rank>,1>&,const Array<P_numtype,N_rank>&);
00091 
00092 /*
00093  * Declaration of class Array
00094  */
00095 
00096 // NEEDS_WORK: Array should inherit protected from MemoryBlockReference.
00097 // To make this work, need to expose MemoryBlockReference::numReferences()
00098 // and make Array<P,N2> a friend of Array<P,N> for slicing.
00099 
00100 template<typename P_numtype, int N_rank>
00101 class Array : public MemoryBlockReference<P_numtype> 
00102 #ifdef BZ_NEW_EXPRESSION_TEMPLATES
00103     , public ETBase<Array<P_numtype,N_rank> >
00104 #endif
00105 {
00106 
00107 private:
00108     typedef MemoryBlockReference<P_numtype> T_base;
00109     using T_base::data_;
00110 
00111 public:
00113     // Public Types
00115 
00116     /*
00117      * T_numtype  is the numeric type stored in the array.
00118      * T_index    is a vector type which can be used to access elements
00119      *            of many-dimensional arrays.
00120      * T_array    is the array type itself -- Array<T_numtype, N_rank>
00121      * T_iterator is a a fast iterator for the array, used for expression
00122      *            templates
00123      * iterator   is a STL-style iterator
00124      * const_iterator is an STL-style const iterator
00125      */
00126 
00127     typedef P_numtype                T_numtype;
00128     typedef TinyVector<int, N_rank>  T_index;
00129     typedef Array<T_numtype, N_rank> T_array;
00130     typedef FastArrayIterator<T_numtype, N_rank> T_iterator;
00131 
00132     typedef ArrayIterator<T_numtype,N_rank> iterator;
00133     typedef ConstArrayIterator<T_numtype,N_rank> const_iterator;
00134 
00135     static const int _bz_rank = N_rank;
00136 
00138     // Constructors                             //
00140 
00141     
00142     /*
00143      * Construct an array from an array expression.
00144      */
00145 
00146     template<typename T_expr>
00147     explicit Array(_bz_ArrayExpr<T_expr> expr);
00148 
00149     /*
00150      * Any missing length arguments will have their value taken from the
00151      * last argument.  For example,
00152      *   Array<int,3> A(32,64);
00153      * will create a 32x64x64 array.  This is handled by setupStorage().
00154      */
00155 
00156     Array(GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00157         : storage_(storage)
00158     {
00159         length_ = 0;
00160         stride_ = 0;
00161         zeroOffset_ = 0;
00162     }
00163 
00164     explicit Array(int length0, 
00165         GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00166         : storage_(storage)
00167     {
00168         length_[0] = length0;
00169         setupStorage(0);
00170     }
00171 
00172     Array(int length0, int length1,
00173         GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00174         : storage_(storage)
00175     {
00176         BZPRECONDITION(N_rank >= 2);
00177         TAU_TYPE_STRING(p1, "Array<T,N>::Array() [T="
00178             + CT(T_numtype) + ",N=" + CT(N_rank) + "]");
00179         TAU_PROFILE(p1, "void (int,int)", TAU_BLITZ);
00180 
00181         length_[0] = length0;
00182         length_[1] = length1;
00183         setupStorage(1);
00184     }
00185 
00186     Array(int length0, int length1, int length2,
00187         GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00188         : storage_(storage)
00189     {
00190         BZPRECONDITION(N_rank >= 3);
00191         length_[0] = length0;
00192         length_[1] = length1;
00193         length_[2] = length2;
00194         setupStorage(2);
00195     }
00196 
00197     Array(int length0, int length1, int length2, int length3,
00198         GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00199         : storage_(storage)
00200     {
00201         BZPRECONDITION(N_rank >= 4);
00202         length_[0] = length0;
00203         length_[1] = length1;
00204         length_[2] = length2;
00205         length_[3] = length3;
00206         setupStorage(3);
00207     }
00208 
00209     Array(int length0, int length1, int length2, int length3, int length4,
00210         GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00211         : storage_(storage)
00212     {
00213         BZPRECONDITION(N_rank >= 5);
00214         length_[0] = length0;
00215         length_[1] = length1;
00216         length_[2] = length2;
00217         length_[3] = length3;
00218         length_[4] = length4;
00219         setupStorage(4);
00220     }
00221 
00222     Array(int length0, int length1, int length2, int length3, int length4,
00223         int length5,
00224         GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00225         : storage_(storage)
00226     {
00227         BZPRECONDITION(N_rank >= 6);
00228         length_[0] = length0;
00229         length_[1] = length1;
00230         length_[2] = length2;
00231         length_[3] = length3;
00232         length_[4] = length4;
00233         length_[5] = length5;
00234         setupStorage(5);
00235     }
00236 
00237     Array(int length0, int length1, int length2, int length3, int length4,
00238         int length5, int length6,
00239         GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00240         : storage_(storage)
00241     {
00242         BZPRECONDITION(N_rank >= 7);
00243         length_[0] = length0;
00244         length_[1] = length1;
00245         length_[2] = length2;
00246         length_[3] = length3;
00247         length_[4] = length4;
00248         length_[5] = length5;
00249         length_[6] = length6;
00250         setupStorage(6);
00251     }
00252 
00253     Array(int length0, int length1, int length2, int length3, int length4,
00254         int length5, int length6, int length7,
00255         GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00256         : storage_(storage)
00257     {
00258         BZPRECONDITION(N_rank >= 8);
00259         length_[0] = length0;
00260         length_[1] = length1;
00261         length_[2] = length2;
00262         length_[3] = length3;
00263         length_[4] = length4;
00264         length_[5] = length5;
00265         length_[6] = length6;
00266         length_[7] = length7;
00267         setupStorage(7);
00268     }
00269 
00270     Array(int length0, int length1, int length2, int length3, int length4,
00271         int length5, int length6, int length7, int length8,
00272         GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00273         : storage_(storage)
00274     {
00275         BZPRECONDITION(N_rank >= 9);
00276         length_[0] = length0;
00277         length_[1] = length1;
00278         length_[2] = length2;
00279         length_[3] = length3;
00280         length_[4] = length4;
00281         length_[5] = length5;
00282         length_[6] = length6;
00283         length_[7] = length7;
00284         length_[8] = length8;
00285         setupStorage(8);
00286     }
00287 
00288     Array(int length0, int length1, int length2, int length3, int length4,
00289         int length5, int length6, int length7, int length8, int length9,
00290         GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00291         : storage_(storage)
00292     {
00293         BZPRECONDITION(N_rank >= 10);
00294         length_[0] = length0;
00295         length_[1] = length1;
00296         length_[2] = length2;
00297         length_[3] = length3;
00298         length_[4] = length4;
00299         length_[5] = length5;
00300         length_[6] = length6;
00301         length_[7] = length7;
00302         length_[8] = length8;
00303         length_[9] = length9;
00304         setupStorage(9);
00305     }
00306 
00307     Array(int length0, int length1, int length2, int length3, int length4,
00308         int length5, int length6, int length7, int length8, int length9,
00309         int length10,
00310         GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00311         : storage_(storage)
00312     {
00313         BZPRECONDITION(N_rank >= 11);
00314         length_[0] = length0;
00315         length_[1] = length1;
00316         length_[2] = length2;
00317         length_[3] = length3;
00318         length_[4] = length4;
00319         length_[5] = length5;
00320         length_[6] = length6;
00321         length_[7] = length7;
00322         length_[8] = length8;
00323         length_[9] = length9;
00324         length_[10] = length10;
00325         setupStorage(10);
00326     }
00327 
00328     /*
00329      * Construct an array from an existing block of memory.  Ownership
00330      * is not acquired (this is provided for backwards compatibility).
00331      */
00332     Array(T_numtype* restrict dataFirst, TinyVector<int, N_rank> shape,
00333         GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00334       : MemoryBlockReference<T_numtype>(_bz_returntype<sizeType>::product(shape), dataFirst, 
00335           neverDeleteData),
00336         storage_(storage)
00337     {
00338         BZPRECONDITION(dataFirst != 0);
00339 
00340         length_ = shape;
00341         computeStrides();
00342         data_ += zeroOffset_;
00343     }
00344 
00345     /*
00346      * Construct an array from an existing block of memory, with a
00347      * given set of strides.  Ownership is not acquired (i.e. the memory
00348      * block will not be freed by Blitz++).
00349      */
00350     Array(T_numtype* restrict dataFirst, TinyVector<int, N_rank> shape,
00351         TinyVector<diffType, N_rank> stride, 
00352         GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00353       : MemoryBlockReference<T_numtype>(_bz_returntype<sizeType>::product(shape), dataFirst, 
00354           neverDeleteData),
00355         storage_(storage)
00356     {
00357         BZPRECONDITION(dataFirst != 0);
00358 
00359         length_ = shape;
00360         stride_ = stride;
00361         calculateZeroOffset();
00362         data_ += zeroOffset_;
00363     }
00364 
00365     /*
00366      * Construct an array from an existing block of memory.
00367      */
00368     Array(T_numtype* restrict dataFirst, TinyVector<int, N_rank> shape,
00369         preexistingMemoryPolicy deletionPolicy,
00370         GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00371       : MemoryBlockReference<T_numtype>(_bz_returntype<sizeType>::product(shape), dataFirst, 
00372             deletionPolicy),
00373         storage_(storage)
00374     {
00375         BZPRECONDITION(dataFirst != 0);
00376 
00377         length_ = shape;
00378         computeStrides();
00379         data_ += zeroOffset_;
00380 
00381         if (deletionPolicy == duplicateData)
00382             reference(copy());
00383     }
00384 
00385     /*
00386      * Construct an array from an existing block of memory, with a
00387      * given set of strides.  
00388      */
00389     Array(T_numtype* restrict dataFirst, TinyVector<int, N_rank> shape,
00390         TinyVector<diffType, N_rank> stride,
00391         preexistingMemoryPolicy deletionPolicy,
00392         GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00393       : MemoryBlockReference<T_numtype>(_bz_returntype<sizeType>::product(shape), dataFirst, 
00394           deletionPolicy),
00395         storage_(storage)
00396     {
00397         BZPRECONDITION(dataFirst != 0);
00398 
00399         length_ = shape;
00400         stride_ = stride;
00401         calculateZeroOffset();
00402         data_ += zeroOffset_;
00403 
00404         if (deletionPolicy == duplicateData)
00405             reference(copy());
00406     }
00407 
00408     /*
00409      * This constructor takes an extent (length) vector and storage format.
00410      */
00411 
00412     Array(const TinyVector<int, N_rank>& extent, 
00413         GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00414         : storage_(storage)
00415     {
00416         length_ = extent;
00417         setupStorage(N_rank - 1);
00418     }
00419 
00420     /*
00421      * This construct takes a vector of bases (lbounds) and a vector of
00422      * extents.
00423      */
00424 
00425     Array(const TinyVector<int, N_rank>& lbounds,
00426         const TinyVector<int, N_rank>& extent,
00427         const GeneralArrayStorage<N_rank>& storage 
00428            = GeneralArrayStorage<N_rank>());
00429 
00430     /*
00431      * These constructors allow arbitrary bases (starting indices) to be set.
00432      * e.g. Array<int,2> A(Range(10,20), Range(20,30))
00433      * will create an 11x11 array whose indices are 10..20 and 20..30
00434      */
00435     Array(Range r0, 
00436         GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00437         : storage_(storage)
00438     {
00439         BZPRECONDITION(r0.isAscendingContiguous());
00440 
00441         length_[0] = r0.length();
00442         storage_.setBase(0, r0.first());
00443         setupStorage(0);
00444     }
00445 
00446     Array(Range r0, Range r1,
00447         GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00448         : storage_(storage)
00449     {
00450         BZPRECONDITION(r0.isAscendingContiguous() && 
00451             r1.isAscendingContiguous());
00452 
00453         length_[0] = r0.length();
00454         storage_.setBase(0, r0.first());
00455         length_[1] = r1.length();
00456         storage_.setBase(1, r1.first());
00457 
00458         setupStorage(1);
00459     }
00460 
00461     Array(Range r0, Range r1, Range r2,
00462         GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00463         : storage_(storage)
00464     {
00465         BZPRECONDITION(r0.isAscendingContiguous() &&
00466             r1.isAscendingContiguous() && r2.isAscendingContiguous());
00467 
00468         length_[0] = r0.length();
00469         storage_.setBase(0, r0.first());
00470         length_[1] = r1.length();
00471         storage_.setBase(1, r1.first());
00472         length_[2] = r2.length();
00473         storage_.setBase(2, r2.first());
00474 
00475         setupStorage(2);
00476     }
00477 
00478     Array(Range r0, Range r1, Range r2, Range r3,
00479         GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00480         : storage_(storage)
00481     {
00482         BZPRECONDITION(r0.isAscendingContiguous() &&
00483             r1.isAscendingContiguous() && r2.isAscendingContiguous()
00484             && r3.isAscendingContiguous());
00485 
00486         length_[0] = r0.length();
00487         storage_.setBase(0, r0.first());
00488         length_[1] = r1.length();
00489         storage_.setBase(1, r1.first());
00490         length_[2] = r2.length();
00491         storage_.setBase(2, r2.first());
00492         length_[3] = r3.length();
00493         storage_.setBase(3, r3.first());
00494 
00495         setupStorage(3);
00496     }
00497 
00498     Array(Range r0, Range r1, Range r2, Range r3, Range r4,
00499         GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00500         : storage_(storage)
00501     {
00502         BZPRECONDITION(r0.isAscendingContiguous() &&
00503             r1.isAscendingContiguous() && r2.isAscendingContiguous()
00504             && r3.isAscendingContiguous() && r4.isAscendingContiguous());
00505 
00506         length_[0] = r0.length();
00507         storage_.setBase(0, r0.first());
00508         length_[1] = r1.length();
00509         storage_.setBase(1, r1.first());
00510         length_[2] = r2.length();
00511         storage_.setBase(2, r2.first());
00512         length_[3] = r3.length();
00513         storage_.setBase(3, r3.first());
00514         length_[4] = r4.length();
00515         storage_.setBase(4, r4.first());
00516 
00517         setupStorage(4);
00518     }
00519 
00520     Array(Range r0, Range r1, Range r2, Range r3, Range r4, Range r5,
00521         GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00522         : storage_(storage)
00523     {
00524         BZPRECONDITION(r0.isAscendingContiguous() &&
00525             r1.isAscendingContiguous() && r2.isAscendingContiguous()
00526             && r3.isAscendingContiguous() && r4.isAscendingContiguous()
00527             && r5.isAscendingContiguous());
00528 
00529         length_[0] = r0.length();
00530         storage_.setBase(0, r0.first());
00531         length_[1] = r1.length();
00532         storage_.setBase(1, r1.first());
00533         length_[2] = r2.length();
00534         storage_.setBase(2, r2.first());
00535         length_[3] = r3.length();
00536         storage_.setBase(3, r3.first());
00537         length_[4] = r4.length();
00538         storage_.setBase(4, r4.first());
00539         length_[5] = r5.length();
00540         storage_.setBase(5, r5.first());
00541 
00542         setupStorage(5);
00543     }
00544 
00545     Array(Range r0, Range r1, Range r2, Range r3, Range r4, Range r5,
00546         Range r6,
00547         GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00548         : storage_(storage)
00549     {
00550         BZPRECONDITION(r0.isAscendingContiguous() &&
00551             r1.isAscendingContiguous() && r2.isAscendingContiguous()
00552             && r3.isAscendingContiguous() && r4.isAscendingContiguous()
00553             && r5.isAscendingContiguous() && r6.isAscendingContiguous());
00554 
00555         length_[0] = r0.length();
00556         storage_.setBase(0, r0.first());
00557         length_[1] = r1.length();
00558         storage_.setBase(1, r1.first());
00559         length_[2] = r2.length();
00560         storage_.setBase(2, r2.first());
00561         length_[3] = r3.length();
00562         storage_.setBase(3, r3.first());
00563         length_[4] = r4.length();
00564         storage_.setBase(4, r4.first());
00565         length_[5] = r5.length();
00566         storage_.setBase(5, r5.first());
00567         length_[6] = r6.length();
00568         storage_.setBase(6, r6.first());
00569 
00570         setupStorage(6);
00571     }
00572 
00573     Array(Range r0, Range r1, Range r2, Range r3, Range r4, Range r5,
00574         Range r6, Range r7,
00575         GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00576         : storage_(storage)
00577     {
00578         BZPRECONDITION(r0.isAscendingContiguous() &&
00579             r1.isAscendingContiguous() && r2.isAscendingContiguous()
00580             && r3.isAscendingContiguous() && r4.isAscendingContiguous()
00581             && r5.isAscendingContiguous() && r6.isAscendingContiguous()
00582             && r7.isAscendingContiguous());
00583 
00584         length_[0] = r0.length();
00585         storage_.setBase(0, r0.first());
00586         length_[1] = r1.length();
00587         storage_.setBase(1, r1.first());
00588         length_[2] = r2.length();
00589         storage_.setBase(2, r2.first());
00590         length_[3] = r3.length();
00591         storage_.setBase(3, r3.first());
00592         length_[4] = r4.length();
00593         storage_.setBase(4, r4.first());
00594         length_[5] = r5.length();
00595         storage_.setBase(5, r5.first());
00596         length_[6] = r6.length();
00597         storage_.setBase(6, r6.first());
00598         length_[7] = r7.length();
00599         storage_.setBase(7, r7.first());
00600 
00601         setupStorage(7);
00602     }
00603 
00604     Array(Range r0, Range r1, Range r2, Range r3, Range r4, Range r5,
00605         Range r6, Range r7, Range r8,
00606         GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00607         : storage_(storage)
00608     {
00609         BZPRECONDITION(r0.isAscendingContiguous() &&
00610             r1.isAscendingContiguous() && r2.isAscendingContiguous()
00611             && r3.isAscendingContiguous() && r4.isAscendingContiguous()
00612             && r5.isAscendingContiguous() && r6.isAscendingContiguous()
00613             && r7.isAscendingContiguous() && r8.isAscendingContiguous());
00614 
00615         length_[0] = r0.length();
00616         storage_.setBase(0, r0.first());
00617         length_[1] = r1.length();
00618         storage_.setBase(1, r1.first());
00619         length_[2] = r2.length();
00620         storage_.setBase(2, r2.first());
00621         length_[3] = r3.length();
00622         storage_.setBase(3, r3.first());
00623         length_[4] = r4.length();
00624         storage_.setBase(4, r4.first());
00625         length_[5] = r5.length();
00626         storage_.setBase(5, r5.first());
00627         length_[6] = r6.length();
00628         storage_.setBase(6, r6.first());
00629         length_[7] = r7.length();
00630         storage_.setBase(7, r7.first());
00631         length_[8] = r8.length();
00632         storage_.setBase(8, r8.first());
00633 
00634         setupStorage(8);
00635     }
00636 
00637     Array(Range r0, Range r1, Range r2, Range r3, Range r4, Range r5,
00638         Range r6, Range r7, Range r8, Range r9,
00639         GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00640         : storage_(storage)
00641     {
00642         BZPRECONDITION(r0.isAscendingContiguous() &&
00643             r1.isAscendingContiguous() && r2.isAscendingContiguous()
00644             && r3.isAscendingContiguous() && r4.isAscendingContiguous()
00645             && r5.isAscendingContiguous() && r6.isAscendingContiguous()
00646             && r7.isAscendingContiguous() && r8.isAscendingContiguous()
00647             && r9.isAscendingContiguous());
00648 
00649         length_[0] = r0.length();
00650         storage_.setBase(0, r0.first());
00651         length_[1] = r1.length();
00652         storage_.setBase(1, r1.first());
00653         length_[2] = r2.length();
00654         storage_.setBase(2, r2.first());
00655         length_[3] = r3.length();
00656         storage_.setBase(3, r3.first());
00657         length_[4] = r4.length();
00658         storage_.setBase(4, r4.first());
00659         length_[5] = r5.length();
00660         storage_.setBase(5, r5.first());
00661         length_[6] = r6.length();
00662         storage_.setBase(6, r6.first());
00663         length_[7] = r7.length();
00664         storage_.setBase(7, r7.first());
00665         length_[8] = r8.length();
00666         storage_.setBase(8, r8.first());
00667         length_[9] = r9.length();
00668         storage_.setBase(9, r9.first());
00669 
00670         setupStorage(9);
00671     }
00672 
00673     Array(Range r0, Range r1, Range r2, Range r3, Range r4, Range r5,
00674         Range r6, Range r7, Range r8, Range r9, Range r10,
00675         GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
00676         : storage_(storage)
00677     {
00678         BZPRECONDITION(r0.isAscendingContiguous() &&
00679             r1.isAscendingContiguous() && r2.isAscendingContiguous()
00680             && r3.isAscendingContiguous() && r4.isAscendingContiguous()
00681             && r5.isAscendingContiguous() && r6.isAscendingContiguous()
00682             && r7.isAscendingContiguous() && r8.isAscendingContiguous()
00683             && r9.isAscendingContiguous() && r10.isAscendingContiguous());
00684 
00685         length_[0] = r0.length();
00686         storage_.setBase(0, r0.first());
00687         length_[1] = r1.length();
00688         storage_.setBase(1, r1.first());
00689         length_[2] = r2.length();
00690         storage_.setBase(2, r2.first());
00691         length_[3] = r3.length();
00692         storage_.setBase(3, r3.first());
00693         length_[4] = r4.length();
00694         storage_.setBase(4, r4.first());
00695         length_[5] = r5.length();
00696         storage_.setBase(5, r5.first());
00697         length_[6] = r6.length();
00698         storage_.setBase(6, r6.first());
00699         length_[7] = r7.length();
00700         storage_.setBase(7, r7.first());
00701         length_[8] = r8.length();
00702         storage_.setBase(8, r8.first());
00703         length_[9] = r9.length();
00704         storage_.setBase(9, r9.first());
00705         length_[10] = r10.length();
00706         storage_.setBase(10, r10.first());
00707 
00708         setupStorage(10);
00709     }
00710 
00711     /*
00712      * Create a reference of another array
00713      */
00714     Array(const Array<T_numtype, N_rank>& array)
00715 #ifdef BZ_NEW_EXPRESSION_TEMPLATES
00716         : MemoryBlockReference<T_numtype>(),
00717           ETBase< Array<T_numtype, N_rank> >(array)
00718 #else
00719         : MemoryBlockReference<T_numtype>()
00720 #endif
00721     {
00722         // NEEDS_WORK: this const_cast is a tad ugly.
00723         reference(const_cast<T_array&>(array));
00724     }
00725 
00726     /*
00727      * These constructors are used for creating interlaced arrays (see
00728      * <blitz/arrayshape.h>
00729      */
00730     Array(const TinyVector<int,N_rank-1>& shape,
00731         int lastExtent, const GeneralArrayStorage<N_rank>& storage);
00732     //Array(const TinyVector<Range,N_rank-1>& shape,
00733     //    int lastExtent, const GeneralArrayStorage<N_rank>& storage);
00734 
00735     /*
00736      * These constructors make the array a view of a subportion of another
00737      * array.  If there fewer than N_rank Range arguments provided, no
00738      * slicing is performed in the unspecified ranks.
00739      * e.g. Array<int,3> A(20,20,20);
00740      *      Array<int,3> B(A, Range(5,15));
00741      * is equivalent to:
00742      *      Array<int,3> B(A, Range(5,15), Range::all(), Range::all());
00743      */
00744     Array(Array<T_numtype, N_rank>& array, Range r0)
00745     {
00746         constructSubarray(array, r0);
00747     }
00748 
00749     Array(Array<T_numtype, N_rank>& array, Range r0, Range r1)
00750     {
00751         constructSubarray(array, r0, r1);
00752     }
00753 
00754     Array(Array<T_numtype, N_rank>& array, Range r0, Range r1, Range r2)
00755     {
00756         constructSubarray(array, r0, r1, r2);
00757     }
00758 
00759     Array(Array<T_numtype, N_rank>& array, Range r0, Range r1, Range r2,
00760         Range r3)
00761     {
00762         constructSubarray(array, r0, r1, r2, r3);
00763     }
00764 
00765     Array(Array<T_numtype, N_rank>& array, Range r0, Range r1, Range r2,
00766         Range r3, Range r4)
00767     {
00768         constructSubarray(array, r0, r1, r2, r3, r4);
00769     }
00770 
00771     Array(Array<T_numtype, N_rank>& array, Range r0, Range r1, Range r2,
00772         Range r3, Range r4, Range r5)
00773     {
00774         constructSubarray(array, r0, r1, r2, r3, r4, r5);
00775     }
00776 
00777     Array(Array<T_numtype, N_rank>& array, Range r0, Range r1, Range r2,
00778         Range r3, Range r4, Range r5, Range r6)
00779     {
00780         constructSubarray(array, r0, r1, r2, r3, r4, r5, r6);
00781     }
00782 
00783     Array(Array<T_numtype, N_rank>& array, Range r0, Range r1, Range r2,
00784         Range r3, Range r4, Range r5, Range r6, Range r7)
00785     {
00786         constructSubarray(array, r0, r1, r2, r3, r4, r5, r6, r7);
00787     }
00788 
00789     Array(Array<T_numtype, N_rank>& array, Range r0, Range r1, Range r2,
00790         Range r3, Range r4, Range r5, Range r6, Range r7, Range r8)
00791     {
00792         constructSubarray(array, r0, r1, r2, r3, r4, r5, r6, r7, r8);
00793     }
00794 
00795     Array(Array<T_numtype, N_rank>& array, Range r0, Range r1, Range r2,
00796         Range r3, Range r4, Range r5, Range r6, Range r7, Range r8, Range r9)
00797     {
00798         constructSubarray(array, r0, r1, r2, r3, r4, r5, r6, r7, r8, r9);
00799     }
00800 
00801     Array(Array<T_numtype, N_rank>& array, Range r0, Range r1, Range r2,
00802         Range r3, Range r4, Range r5, Range r6, Range r7, Range r8, Range r9,
00803         Range r10)
00804     {
00805         constructSubarray(array, r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10);
00806     }
00807 
00808     Array(Array<T_numtype, N_rank>& array, 
00809         const RectDomain<N_rank>& subdomain)
00810     {
00811         constructSubarray(array, subdomain);
00812     }
00813 
00814     /* Constructor added by Julian Cummings */
00815     Array(Array<T_numtype, N_rank>& array, 
00816         const StridedDomain<N_rank>& subdomain)
00817     {
00818         constructSubarray(array, subdomain);
00819     }
00820 
00821     /*
00822      * This constructor is invoked by the operator()'s which take
00823      * a combination of integer and Range arguments.  It's not intended
00824      * for end-user use.
00825      */
00826     template<int N_rank2, typename R0, typename R1, typename R2, typename R3, typename R4,
00827         typename R5, typename R6, typename R7, typename R8, typename R9, typename R10>
00828     Array(Array<T_numtype,N_rank2>& array, R0 r0, R1 r1, R2 r2,
00829         R3 r3, R4 r4, R5 r5, R6 r6, R7 r7, R8 r8, R9 r9, R10 r10)
00830     {
00831         constructSlice(array, r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10);
00832     }
00833 
00835     // Member functions
00837 
00838     const TinyVector<int, N_rank>&    base() const
00839     { return storage_.base(); }
00840 
00841     int                               base(int rank) const
00842     { return storage_.base(rank); }
00843 
00844     iterator                          begin() 
00845     { return iterator(*this); }
00846 
00847     const_iterator                    begin() const
00848     { return const_iterator(*this); }
00849 
00850     T_iterator                        beginFast() const
00851     { return T_iterator(*this); }
00852 
00853     // Deprecated: now extractComponent(...)
00854     template<typename P_numtype2>
00855     Array<P_numtype2,N_rank>          chopComponent(P_numtype2 a, int compNum,
00856                                                     int numComponents) const
00857     { return extractComponent(a, compNum, numComponents); }
00858 
00859     int                               cols() const
00860     { return length_[1]; }
00861 
00862     int                               columns() const
00863     { return length_[1]; }
00864 
00865     T_array                           copy() const;
00866 
00867     // data_ always refers to the point (0,0,...,0) which may
00868     // not be in the array if the base is not zero in each rank.
00869     // These data() routines return a pointer to the first
00870     // element in the array (but note that it may not be
00871     // stored first in memory if some ranks are stored descending).
00872 
00873     diffType                               dataOffset() const
00874   { return dot(storage_.base(), stride_); }
00875 
00876     const T_numtype* restrict         data() const
00877     { return data_ + dataOffset(); }
00878 
00879     T_numtype* restrict               data() 
00880     { return data_ + dataOffset(); }
00881 
00882     // These dataZero() routines refer to the point (0,0,...,0)
00883     // which may not be in the array if the bases are nonzero.
00884     
00885     const T_numtype* restrict         dataZero() const
00886     { return data_; }
00887 
00888     T_numtype* restrict               dataZero()
00889     { return data_; }
00890 
00891     // These dataFirst() routines refer to the element in the
00892     // array which falls first in memory.
00893 
00894     diffType                               dataFirstOffset() const
00895     {
00896       diffType pos = 0;
00897 
00898         // Used to use tinyvector expressions:
00899         // return data_ + dot(storage_.base()
00900         //     + (1 - storage_.ascendingFlag()) * (length_ - 1), stride_);
00901 
00902         for (int i=0; i < N_rank; ++i)
00903            pos += (storage_.base(i) + (1-storage_.isRankStoredAscending(i)) *
00904        (length_(i)-1)) * stride_(i);
00905 
00906         return pos;
00907     }
00908     
00909     const T_numtype* restrict         dataFirst() const
00910     { return data_ + dataFirstOffset(); }
00911 
00912     T_numtype* restrict               dataFirst()
00913     { return data_ + dataFirstOffset(); }
00914 
00915     int                               depth() const
00916     { return length_[2]; }
00917 
00918     int                               dimensions() const
00919     { return N_rank; }
00920 
00921     RectDomain<N_rank>                domain() const
00922     { return RectDomain<N_rank>(lbound(), ubound()); }
00923 
00924     void dumpStructureInformation(ostream& os = cout) const;
00925 
00926     iterator                          end()
00927     { return iterator(*this,0); }
00928 
00929     const_iterator                    end() const
00930     { return const_iterator(*this,0); }
00931 
00932     int                               extent(int rank) const
00933     { return length_[rank]; }
00934 
00935     const TinyVector<int,N_rank>&     extent() const
00936     { return length_; }
00937 
00938     template<typename P_numtype2>
00939     Array<P_numtype2,N_rank>          extractComponent(P_numtype2, int compNum,
00940                                                        int numComponents) const;
00941 
00942     void                              free() 
00943     {
00944         T_base::changeToNullBlock();
00945         length_ = 0;
00946     }
00947  
00948     bool                              isMajorRank(int rank) const 
00949     { return storage_.ordering(rank) == N_rank-1; }
00950     bool                              isMinorRank(int rank) const 
00951     { return storage_.ordering(rank) != N_rank-1; }
00952     bool                              isRankStoredAscending(int rank) const 
00953     { return storage_.isRankStoredAscending(rank); }
00954 
00955     bool                              isStorageContiguous() const;
00956 
00957     int                               lbound(int rank) const 
00958     { return base(rank); }
00959     TinyVector<int,N_rank>            lbound() const 
00960     { return base(); }
00961 
00962     int                               length(int rank) const 
00963     { return length_[rank]; }
00964     const TinyVector<int, N_rank>&    length() const 
00965     { return length_; }
00966 
00967     void                              makeUnique();
00968 
00969     sizeType                               numElements() const 
00970     { return _bz_returntype<sizeType>::product(length_); }
00971 
00972     // NEEDS_WORK -- Expose the numReferences() method
00973     // MemoryBlockReference<T_numtype>::numReferences;
00974 
00975     // The storage_.ordering_ array is a list of dimensions from
00976     // the most minor (stride 1) to major dimension.  Generally,
00977     // ordering(0) will return the dimension which has the smallest
00978     // stride, and ordering(N_rank-1) will return the dimension with
00979     // the largest stride.
00980     int                               ordering(int storageRankIndex) const
00981     { return storage_.ordering(storageRankIndex); }
00982 
00983     const TinyVector<int, N_rank>&    ordering() const
00984     { return storage_.ordering(); }
00985 
00986     void                              transposeSelf(int r0, int r1, int r2=0, 
00987         int r3=0, int r4=0, int r5=0, int r6=0, int r7=0, int r8=0, int 
00988         r9=0, int r10=0);
00989     T_array                           transpose(int r0, int r1, int r2=0,
00990         int r3=0, int r4=0, int r5=0, int r6=0, int r7=0, int r8=0, int
00991         r9=0, int r10=0) const;
00992 
00993     int                               rank() const
00994     { return N_rank; }
00995 
00996     void                              reference(const T_array&);
00997     void                              weakReference(const T_array&);
00998 
00999     // Added by Derrick Bass
01000     T_array                           reindex(const TinyVector<int,N_rank>&);
01001     void                              reindexSelf(
01002                                         const TinyVector<int,N_rank>&);
01003 
01004     void                              resize(int extent);
01005     void                              resize(int extent1, int extent2);
01006     void                              resize(int extent1, int extent2,
01007                                         int extent3);
01008     void                              resize(int extent1, int extent2,
01009                                         int extent3, int extent4);
01010     void                              resize(int extent1, int extent2,
01011                                         int extent3, int extent4, int extent5);
01012     void                              resize(int extent1, int extent2,
01013                                         int extent3, int extent4, int extent5,
01014                                         int extent6);
01015     void                              resize(int extent1, int extent2,
01016                                         int extent3, int extent4, int extent5,
01017                                         int extent6, int extent7);
01018     void                              resize(int extent1, int extent2,
01019                                         int extent3, int extent4, int extent5,
01020                                         int extent6, int extent7, int extent8);
01021     void                              resize(int extent1, int extent2,
01022                                         int extent3, int extent4, int extent5,
01023                                         int extent6, int extent7, int extent8,
01024                                         int extent9);
01025     void                              resize(int extent1, int extent2,
01026                                         int extent3, int extent4, int extent5,
01027                                         int extent6, int extent7, int extent8,
01028                                         int extent9, int extent10);
01029     void                              resize(int extent1, int extent2,
01030                                         int extent3, int extent4, int extent5,
01031                                         int extent6, int extent7, int extent8,
01032                                         int extent9, int extent10, 
01033                                         int extent11);
01034 
01035 
01036     void                              resize(Range r1);
01037     void                              resize(Range r1, Range r2);
01038     void                              resize(Range r1, Range r2, Range r3);
01039     void                              resize(Range r1, Range r2, Range r3,
01040                                         Range r4);
01041     void                              resize(Range r1, Range r2, Range r3,
01042                                         Range r4, Range r5);
01043     void                              resize(Range r1, Range r2, Range r3,
01044                                         Range r4, Range r5, Range r6);
01045     void                              resize(Range r1, Range r2, Range r3,
01046                                         Range r4, Range r5, Range r6,
01047                                         Range r7);
01048     void                              resize(Range r1, Range r2, Range r3,
01049                                         Range r4, Range r5, Range r6,
01050                                         Range r7, Range r8);
01051     void                              resize(Range r1, Range r2, Range r3,
01052                                         Range r4, Range r5, Range r6,
01053                                         Range r7, Range r8, Range r9);
01054     void                              resize(Range r1, Range r2, Range r3,
01055                                         Range r4, Range r5, Range r6,
01056                                         Range r7, Range r8, Range r9, 
01057                                         Range r10);
01058     void                              resize(Range r1, Range r2, Range r3,
01059                                         Range r4, Range r5, Range r6,
01060                                         Range r7, Range r8, Range r9, 
01061                                         Range r10, Range r11);
01062 
01063     void                              resize(const TinyVector<int,N_rank>&);
01064  
01065 
01066     void                              resizeAndPreserve(const TinyVector<int,
01067                                                                    N_rank>&);
01068     void                              resizeAndPreserve(int extent);
01069     void                              resizeAndPreserve(int extent1, 
01070                                         int extent2);
01071     void                              resizeAndPreserve(int extent1, 
01072                                         int extent2, int extent3);
01073     void                              resizeAndPreserve(int extent1,
01074                                         int extent2, int extent3, int extent4);
01075     void                              resizeAndPreserve(int extent1,
01076                                         int extent2, int extent3, int extent4,
01077                                         int extent5);
01078     void                              resizeAndPreserve(int extent1,
01079                                         int extent2, int extent3, int extent4,
01080                                         int extent5, int extent6);
01081     void                              resizeAndPreserve(int extent1,
01082                                         int extent2, int extent3, int extent4,
01083                                         int extent5, int extent6, int extent7);
01084     void                              resizeAndPreserve(int extent1,
01085                                         int extent2, int extent3, int extent4,
01086                                         int extent5, int extent6, int extent7,
01087                                         int extent8);
01088     void                              resizeAndPreserve(int extent1,
01089                                         int extent2, int extent3, int extent4,
01090                                         int extent5, int extent6, int extent7,
01091                                         int extent8, int extent9);
01092     void                              resizeAndPreserve(int extent1,
01093                                         int extent2, int extent3, int extent4,
01094                                         int extent5, int extent6, int extent7,
01095                                         int extent8, int extent9, 
01096                                         int extent10);
01097     void                              resizeAndPreserve(int extent1,
01098                                         int extent2, int extent3, int extent4,
01099                                         int extent5, int extent6, int extent7,
01100                                         int extent8, int extent9, int extent10,
01101                                         int extent11);
01102 
01103     // NEEDS_WORK -- resizeAndPreserve(Range,...)
01104     // NEEDS_WORK -- resizeAndPreserve(const Domain<N_rank>&);
01105 
01106     T_array                           reverse(int rank);
01107     void                              reverseSelf(int rank);
01108 
01109     int                               rows() const
01110     { return length_[0]; }
01111     
01112     void                              setStorage(GeneralArrayStorage<N_rank>);
01113     
01114     void                              slice(int rank, Range r);
01115 
01116     const TinyVector<int, N_rank>&    shape() const
01117     { return length_; }
01118 
01119     sizeType                               size() const
01120     { return numElements(); }
01121 
01122     const TinyVector<diffType, N_rank>&    stride() const
01123     { return stride_; }
01124 
01125   diffType                               stride(int rank) const
01126     { return stride_[rank]; }
01127 
01128     bool                              threadLocal(bool disableLock = true) const
01129         { return T_base::lockReferenceCount(!disableLock); }
01130 
01131     int                               ubound(int rank) const
01132     { return base(rank) + length_(rank) - 1; }
01133 
01134     TinyVector<int, N_rank>           ubound() const
01135     { 
01136         TinyVector<int, N_rank> ub;
01137         for (int i=0; i < N_rank; ++i)
01138           ub(i) = base(i) + extent(i) - 1;
01139         // WAS: ub = base() + extent() - 1;
01140         return ub;
01141     }
01142 
01143     int                               zeroOffset() const
01144     { return zeroOffset_; }
01145 
01147     // Debugging routines
01149 
01150     bool isInRangeForDim(int i, int d) const {
01151         return i >= base(d) && (i - base(d)) < length_[d];
01152     }
01153 
01154     bool isInRange(int i0) const {
01155         return i0 >= base(0) && (i0 - base(0)) < length_[0];
01156     }
01157 
01158     bool isInRange(int i0, int i1) const {
01159         return i0 >= base(0) && (i0 - base(0)) < length_[0]
01160             && i1 >= base(1) && (i1 - base(1)) < length_[1];
01161     }
01162 
01163     bool isInRange(int i0, int i1, int i2) const {
01164         return i0 >= base(0) && (i0 - base(0)) < length_[0]
01165             && i1 >= base(1) && (i1 - base(1)) < length_[1]
01166             && i2 >= base(2) && (i2 - base(2)) < length_[2];
01167     }
01168 
01169     bool isInRange(int i0, int i1, int i2, int i3) const {
01170         return i0 >= base(0) && (i0 - base(0)) < length_[0]
01171             && i1 >= base(1) && (i1 - base(1)) < length_[1]
01172             && i2 >= base(2) && (i2 - base(2)) < length_[2]
01173             && i3 >= base(3) && (i3 - base(3)) < length_[3];
01174     }
01175 
01176     bool isInRange(int i0, int i1, int i2, int i3, int i4) const {
01177         return i0 >= base(0) && (i0 - base(0)) < length_[0]
01178             && i1 >= base(1) && (i1 - base(1)) < length_[1]
01179             && i2 >= base(2) && (i2 - base(2)) < length_[2]
01180             && i3 >= base(3) && (i3 - base(3)) < length_[3]
01181             && i4 >= base(4) && (i4 - base(4)) < length_[4];
01182     }
01183 
01184     bool isInRange(int i0, int i1, int i2, int i3, int i4, int i5) const {
01185         return i0 >= base(0) && (i0 - base(0)) < length_[0]
01186             && i1 >= base(1) && (i1 - base(1)) < length_[1]
01187             && i2 >= base(2) && (i2 - base(2)) < length_[2]
01188             && i3 >= base(3) && (i3 - base(3)) < length_[3]
01189             && i4 >= base(4) && (i4 - base(4)) < length_[4]
01190             && i5 >= base(5) && (i5 - base(5)) < length_[5];
01191     }
01192 
01193     bool isInRange(int i0, int i1, int i2, int i3, int i4, int i5, int i6) const {
01194         return i0 >= base(0) && (i0 - base(0)) < length_[0]
01195             && i1 >= base(1) && (i1 - base(1)) < length_[1]
01196             && i2 >= base(2) && (i2 - base(2)) < length_[2]
01197             && i3 >= base(3) && (i3 - base(3)) < length_[3]
01198             && i4 >= base(4) && (i4 - base(4)) < length_[4]
01199             && i5 >= base(5) && (i5 - base(5)) < length_[5]
01200             && i6 >= base(6) && (i6 - base(6)) < length_[6];
01201     }
01202 
01203     bool isInRange(int i0, int i1, int i2, int i3, int i4,
01204         int i5, int i6, int i7) const {
01205         return i0 >= base(0) && (i0 - base(0)) < length_[0]
01206             && i1 >= base(1) && (i1 - base(1)) < length_[1]
01207             && i2 >= base(2) && (i2 - base(2)) < length_[2]
01208             && i3 >= base(3) && (i3 - base(3)) < length_[3]
01209             && i4 >= base(4) && (i4 - base(4)) < length_[4]
01210             && i5 >= base(5) && (i5 - base(5)) < length_[5]
01211             && i6 >= base(6) && (i6 - base(6)) < length_[6]
01212             && i7 >= base(7) && (i7 - base(7)) < length_[7];
01213     }
01214 
01215     bool isInRange(int i0, int i1, int i2, int i3, int i4,
01216         int i5, int i6, int i7, int i8) const {
01217         return i0 >= base(0) && (i0 - base(0)) < length_[0]
01218             && i1 >= base(1) && (i1 - base(1)) < length_[1]
01219             && i2 >= base(2) && (i2 - base(2)) < length_[2]
01220             && i3 >= base(3) && (i3 - base(3)) < length_[3]
01221             && i4 >= base(4) && (i4 - base(4)) < length_[4]
01222             && i5 >= base(5) && (i5 - base(5)) < length_[5]
01223             && i6 >= base(6) && (i6 - base(6)) < length_[6]
01224             && i7 >= base(7) && (i7 - base(7)) < length_[7]
01225             && i8 >= base(8) && (i8 - base(8)) < length_[8];
01226     }
01227 
01228     bool isInRange(int i0, int i1, int i2, int i3, int i4,
01229         int i5, int i6, int i7, int i8, int i9) const {
01230         return i0 >= base(0) && (i0 - base(0)) < length_[0]
01231             && i1 >= base(1) && (i1 - base(1)) < length_[1]
01232             && i2 >= base(2) && (i2 - base(2)) < length_[2]
01233             && i3 >= base(3) && (i3 - base(3)) < length_[3]
01234             && i4 >= base(4) && (i4 - base(4)) < length_[4]
01235             && i5 >= base(5) && (i5 - base(5)) < length_[5]
01236             && i6 >= base(6) && (i6 - base(6)) < length_[6]
01237             && i7 >= base(7) && (i7 - base(7)) < length_[7]
01238             && i8 >= base(8) && (i8 - base(8)) < length_[8]
01239             && i9 >= base(9) && (i9 - base(9)) < length_[9];
01240     }
01241 
01242     bool isInRange(int i0, int i1, int i2, int i3, int i4,
01243         int i5, int i6, int i7, int i8, int i9, int i10) const {
01244         return i0 >= base(0) && (i0 - base(0)) < length_[0]
01245             && i1 >= base(1) && (i1 - base(1)) < length_[1]
01246             && i2 >= base(2) && (i2 - base(2)) < length_[2]
01247             && i3 >= base(3) && (i3 - base(3)) < length_[3]
01248             && i4 >= base(4) && (i4 - base(4)) < length_[4]
01249             && i5 >= base(5) && (i5 - base(5)) < length_[5]
01250             && i6 >= base(6) && (i6 - base(6)) < length_[6]
01251             && i7 >= base(7) && (i7 - base(7)) < length_[7]
01252             && i8 >= base(8) && (i8 - base(8)) < length_[8]
01253             && i9 >= base(9) && (i9 - base(9)) < length_[9]
01254             && i10 >= base(10) && (i10 - base(10)) < length_[10];
01255     }
01256 
01257     bool isInRange(const T_index& index) const {
01258         for (int i=0; i < N_rank; ++i)
01259             if (index[i] < base(i) || (index[i] - base(i)) >= length_[i])
01260                 return false;
01261 
01262         return true;
01263     }
01264 
01265     bool assertInRange(const T_index& BZ_DEBUG_PARAM(index)) const {
01266         BZPRECHECK(isInRange(index), "Array index out of range: " << index
01267             << endl << "Lower bounds: " << storage_.base() << endl
01268             <<         "Length:       " << length_ << endl);
01269         return true;
01270     }
01271 
01272     bool assertInRange(int BZ_DEBUG_PARAM(i0)) const {
01273         BZPRECHECK(isInRange(i0), "Array index out of range: " << i0
01274             << endl << "Lower bounds: " << storage_.base() << endl
01275             <<         "Length:       " << length_ << endl);
01276         return true;
01277     }
01278 
01279     bool assertInRange(int BZ_DEBUG_PARAM(i0), int BZ_DEBUG_PARAM(i1)) const {
01280         BZPRECHECK(isInRange(i0,i1), "Array index out of range: (" 
01281             << i0 << ", " << i1 << ")"
01282             << endl << "Lower bounds: " << storage_.base() << endl
01283             <<         "Length:       " << length_ << endl);
01284         return true;
01285     }
01286 
01287     bool assertInRange(int BZ_DEBUG_PARAM(i0), int BZ_DEBUG_PARAM(i1),
01288         int BZ_DEBUG_PARAM(i2)) const
01289     {
01290         BZPRECHECK(isInRange(i0,i1,i2), "Array index out of range: ("
01291             << i0 << ", " << i1 << ", " << i2 << ")"
01292             << endl << "Lower bounds: " << storage_.base() << endl
01293             <<         "Length:       " << length_ << endl);
01294         return true;
01295     }
01296 
01297     bool assertInRange(int BZ_DEBUG_PARAM(i0), int BZ_DEBUG_PARAM(i1),
01298         int BZ_DEBUG_PARAM(i2), int BZ_DEBUG_PARAM(i3)) const
01299     {
01300         BZPRECHECK(isInRange(i0,i1,i2,i3), "Array index out of range: ("
01301             << i0 << ", " << i1 << ", " << i2 << ", " << i3 << ")"
01302             << endl << "Lower bounds: " << storage_.base() << endl
01303             <<         "Length:       " << length_ << endl);
01304         return true;
01305     }
01306 
01307     bool assertInRange(int BZ_DEBUG_PARAM(i0), int BZ_DEBUG_PARAM(i1),
01308         int BZ_DEBUG_PARAM(i2), int BZ_DEBUG_PARAM(i3),
01309         int BZ_DEBUG_PARAM(i4)) const
01310     {
01311         BZPRECHECK(isInRange(i0,i1,i2,i3,i4), "Array index out of range: ("
01312             << i0 << ", " << i1 << ", " << i2 << ", " << i3 
01313             << ", " << i4 << ")"
01314             << endl << "Lower bounds: " << storage_.base() << endl
01315             <<         "Length:       " << length_ << endl);
01316         return true;
01317     }
01318 
01319     bool assertInRange(int BZ_DEBUG_PARAM(i0), int BZ_DEBUG_PARAM(i1),
01320         int BZ_DEBUG_PARAM(i2), int BZ_DEBUG_PARAM(i3), int BZ_DEBUG_PARAM(i4),
01321         int BZ_DEBUG_PARAM(i5)) const
01322     {
01323         BZPRECHECK(isInRange(i0,i1,i2,i3,i4,i5), "Array index out of range: ("
01324             << i0 << ", " << i1 << ", " << i2 << ", " << i3
01325             << ", " << i4 << ", " << i5 << ")"
01326             << endl << "Lower bounds: " << storage_.base() << endl
01327             <<         "Length:       " << length_ << endl);
01328         return true;
01329     }
01330 
01331     bool assertInRange(int BZ_DEBUG_PARAM(i0), int BZ_DEBUG_PARAM(i1),
01332         int BZ_DEBUG_PARAM(i2), int BZ_DEBUG_PARAM(i3), int BZ_DEBUG_PARAM(i4),
01333         int BZ_DEBUG_PARAM(i5), int BZ_DEBUG_PARAM(i6)) const
01334     {
01335         BZPRECHECK(isInRange(i0,i1,i2,i3,i4,i5,i6), 
01336             "Array index out of range: ("
01337             << i0 << ", " << i1 << ", " << i2 << ", " << i3
01338             << ", " << i4 << ", " << i5 << ", " << i6 << ")"
01339             << endl << "Lower bounds: " << storage_.base() << endl
01340             <<         "Length:       " << length_ << endl);
01341         return true;
01342     }
01343 
01344     bool assertInRange(int BZ_DEBUG_PARAM(i0), int BZ_DEBUG_PARAM(i1),
01345         int BZ_DEBUG_PARAM(i2), int BZ_DEBUG_PARAM(i3), int BZ_DEBUG_PARAM(i4),
01346         int BZ_DEBUG_PARAM(i5), int BZ_DEBUG_PARAM(i6),
01347         int BZ_DEBUG_PARAM(i7)) const
01348     {
01349         BZPRECHECK(isInRange(i0,i1,i2,i3,i4,i5,i6,i7),
01350             "Array index out of range: ("
01351             << i0 << ", " << i1 << ", " << i2 << ", " << i3
01352             << ", " << i4 << ", " << i5 << ", " << i6 << ", " << i7 << ")"
01353             << endl << "Lower bounds: " << storage_.base() << endl
01354             <<         "Length:       " << length_ << endl);
01355         return true;
01356     }
01357 
01358     bool assertInRange(int BZ_DEBUG_PARAM(i0), int BZ_DEBUG_PARAM(i1),
01359         int BZ_DEBUG_PARAM(i2), int BZ_DEBUG_PARAM(i3), int BZ_DEBUG_PARAM(i4),
01360         int BZ_DEBUG_PARAM(i5), int BZ_DEBUG_PARAM(i6), int BZ_DEBUG_PARAM(i7),
01361         int BZ_DEBUG_PARAM(i8)) const
01362     {
01363         BZPRECHECK(isInRange(i0,i1,i2,i3,i4,i5,i6,i7,i8),
01364             "Array index out of range: ("
01365             << i0 << ", " << i1 << ", " << i2 << ", " << i3
01366             << ", " << i4 << ", " << i5 << ", " << i6 << ", " << i7 
01367             << ", " << i8 << ")"
01368             << endl << "Lower bounds: " << storage_.base() << endl
01369             <<         "Length:       " << length_ << endl);
01370         return true;
01371     }
01372 
01373     bool assertInRange(int BZ_DEBUG_PARAM(i0), int BZ_DEBUG_PARAM(i1),
01374         int BZ_DEBUG_PARAM(i2), int BZ_DEBUG_PARAM(i3), int BZ_DEBUG_PARAM(i4),
01375         int BZ_DEBUG_PARAM(i5), int BZ_DEBUG_PARAM(i6), int BZ_DEBUG_PARAM(i7),
01376         int BZ_DEBUG_PARAM(i8), int BZ_DEBUG_PARAM(i9)) const
01377     {
01378         BZPRECHECK(isInRange(i0,i1,i2,i3,i4,i5,i6,i7,i8,i9),
01379             "Array index out of range: ("
01380             << i0 << ", " << i1 << ", " << i2 << ", " << i3
01381             << ", " << i4 << ", " << i5 << ", " << i6 << ", " << i7
01382             << ", " << i8 << ", " << i9 << ")"
01383             << endl << "Lower bounds: " << storage_.base() << endl
01384             <<         "Length:       " << length_ << endl);
01385         return true;
01386     }
01387 
01388     bool assertInRange(int BZ_DEBUG_PARAM(i0), int BZ_DEBUG_PARAM(i1),
01389         int BZ_DEBUG_PARAM(i2), int BZ_DEBUG_PARAM(i3), int BZ_DEBUG_PARAM(i4),
01390         int BZ_DEBUG_PARAM(i5), int BZ_DEBUG_PARAM(i6), int BZ_DEBUG_PARAM(i7),
01391         int BZ_DEBUG_PARAM(i8), int BZ_DEBUG_PARAM(i9),
01392         int BZ_DEBUG_PARAM(i10)) const
01393     {
01394         BZPRECHECK(isInRange(i0,i1,i2,i3,i4,i5,i6,i7,i8,i9,i10),
01395             "Array index out of range: ("
01396             << i0 << ", " << i1 << ", " << i2 << ", " << i3
01397             << ", " << i4 << ", " << i5 << ", " << i6 << ", " << i7
01398             << ", " << i8 << ", " << i9 << ", " << i10 << ")"
01399             << endl << "Lower bounds: " << storage_.base() << endl
01400             <<         "Length:       " << length_ << endl);
01401         return true;
01402     }
01403 
01405     // Subscripting operators
01407 
01408     template<int N_rank2>
01409     const T_numtype& restrict operator()(const TinyVector<int,N_rank2>& index) const
01410     {
01411         assertInRange(index);
01412         return data_[dot(index, stride_)];
01413     }
01414 
01415     template<int N_rank2>
01416     T_numtype& restrict operator()(const TinyVector<int,N_rank2>& index) 
01417     {
01418         assertInRange(index);
01419         return data_[dot(index, stride_)];
01420     }
01421 
01422     const T_numtype& restrict operator()(TinyVector<int,1> index) const
01423     {
01424         assertInRange(index[0]);
01425         return data_[index[0] * stride_[0]];
01426     }
01427 
01428     T_numtype& operator()(TinyVector<int,1> index)
01429     {
01430         assertInRange(index[0]);
01431         return data_[index[0] * stride_[0]];
01432     }
01433 
01434     const T_numtype& restrict operator()(TinyVector<int,2> index) const
01435     {
01436         assertInRange(index[0], index[1]);
01437         return data_[index[0] * stride_[0] 
01438          + index[1] * stride_[1]];
01439     }
01440 
01441     T_numtype& operator()(TinyVector<int,2> index)
01442     {
01443         assertInRange(index[0], index[1]);
01444         return data_[index[0] * stride_[0] 
01445          + index[1] * stride_[1]];
01446     }
01447 
01448     const T_numtype& restrict operator()(TinyVector<int,3> index) const
01449     {
01450         assertInRange(index[0], index[1], index[2]);
01451         return data_[(index[0]) * stride_[0] 
01452          + index[1] * stride_[1]
01453          + index[2] * stride_[2]];
01454     }
01455 
01456     T_numtype& operator()(TinyVector<int,3> index)
01457     {
01458         assertInRange(index[0], index[1], index[2]);
01459         return data_[(index[0]) * stride_[0]
01460          + index[1] * stride_[1]
01461          + index[2] * stride_[2]];
01462     }
01463 
01464     const T_numtype& restrict operator()(const TinyVector<int,4>& index) const
01465     {
01466         assertInRange(index[0], index[1], index[2], index[3]);
01467         return data_[(index[0]) * stride_[0] 
01468          + index[1] * stride_[1]
01469          + index[2] * stride_[2] + index[3] * stride_[3]];
01470     }
01471 
01472     T_numtype& operator()(const TinyVector<int,4>& index)
01473     {
01474         assertInRange(index[0], index[1], index[2], index[3]);
01475         return data_[(index[0]) * stride_[0] 
01476          + index[1] * stride_[1]
01477          + index[2] * stride_[2] + index[3] * stride_[3]];
01478     }
01479 
01480     const T_numtype& restrict operator()(const TinyVector<int,5>& index) const
01481     {
01482         assertInRange(index[0], index[1], index[2], index[3],
01483             index[4]);
01484         return data_[(index[0]) * stride_[0] 
01485          + index[1] * stride_[1]
01486          + index[2] * stride_[2] + index[3] * stride_[3]
01487          + index[4] * stride_[4]];
01488     }
01489 
01490     T_numtype& operator()(const TinyVector<int,5>& index)
01491     {
01492         assertInRange(index[0], index[1], index[2], index[3],
01493             index[4]);
01494         return data_[(index[0]) * stride_[0]
01495          + index[1] * stride_[1]
01496          + index[2] * stride_[2] + index[3] * stride_[3]
01497          + index[4] * stride_[4]];
01498     }
01499 
01500     const T_numtype& restrict operator()(const TinyVector<int,6>& index) const
01501     {
01502         assertInRange(index[0], index[1], index[2], index[3],
01503             index[4], index[5]);
01504         return data_[(index[0]) * stride_[0]
01505          + index[1] * stride_[1]
01506          + index[2] * stride_[2] + index[3] * stride_[3]
01507          + index[4] * stride_[4] + index[5] * stride_[5]];
01508     }
01509 
01510     T_numtype& operator()(const TinyVector<int,6>& index)
01511     {
01512         assertInRange(index[0], index[1], index[2], index[3],
01513             index[4], index[5]);
01514         return data_[(index[0]) * stride_[0]
01515          + index[1] * stride_[1]
01516          + index[2] * stride_[2] + index[3] * stride_[3]
01517          + index[4] * stride_[4] + index[5] * stride_[5]];
01518     }
01519 
01520     const T_numtype& restrict operator()(const TinyVector<int,7>& index) const
01521     {
01522         assertInRange(index[0], index[1], index[2], index[3],
01523             index[4], index[5], index[6]);
01524         return data_[(index[0]) * stride_[0] 
01525          + index[1] * stride_[1]
01526          + index[2] * stride_[2] + index[3] * stride_[3]
01527          + index[4] * stride_[4] + index[5] * stride_[5]
01528          + index[6] * stride_[6]];
01529     }
01530 
01531     T_numtype& operator()(const TinyVector<int,7>& index)
01532     {
01533         assertInRange(index[0], index[1], index[2], index[3],
01534             index[4], index[5], index[6]);
01535         return data_[(index[0]) * stride_[0] 
01536          + index[1] * stride_[1]
01537          + index[2] * stride_[2] + index[3] * stride_[3]
01538          + index[4] * stride_[4] + index[5] * stride_[5]
01539          + index[6] * stride_[6]];
01540     }
01541 
01542     const T_numtype& restrict operator()(const TinyVector<int,8>& index) const
01543     {
01544         assertInRange(index[0], index[1], index[2], index[3],
01545             index[4], index[5], index[6], index[7]);
01546         return data_[(index[0]) * stride_[0]
01547          + index[1] * stride_[1]
01548          + index[2] * stride_[2] + index[3] * stride_[3]
01549          + index[4] * stride_[4] + index[5] * stride_[5]
01550          + index[6] * stride_[6] + index[7] * stride_[7]];
01551     }
01552 
01553     T_numtype& operator()(const TinyVector<int,8>& index)
01554     {
01555         assertInRange(index[0], index[1], index[2], index[3],
01556             index[4], index[5], index[6], index[7]);
01557         return data_[(index[0]) * stride_[0] 
01558          + index[1] * stride_[1]
01559          + index[2] * stride_[2] + index[3] * stride_[3]
01560          + index[4] * stride_[4] + index[5] * stride_[5]
01561          + index[6] * stride_[6] + index[7] * stride_[7]];
01562     }
01563 
01564     const T_numtype& restrict operator()(const TinyVector<int,9>& index) const
01565     {
01566         assertInRange(index[0], index[1], index[2], index[3],
01567             index[4], index[5], index[6], index[7], index[8]);
01568         return data_[(index[0]) * stride_[0]
01569          + index[1] * stride_[1]
01570          + index[2] * stride_[2] + index[3] * stride_[3]
01571          + index[4] * stride_[4] + index[5] * stride_[5]
01572          + index[6] * stride_[6] + index[7] * stride_[7]
01573          + index[8] * stride_[8]];
01574     }
01575 
01576     T_numtype& operator()(const TinyVector<int,9>& index)
01577     {
01578         assertInRange(index[0], index[1], index[2], index[3],
01579             index[4], index[5], index[6], index[7], index[8]);
01580         return data_[(index[0]) * stride_[0]
01581          + index[1] * stride_[1]
01582          + index[2] * stride_[2] + index[3] * stride_[3]
01583          + index[4] * stride_[4] + index[5] * stride_[5]
01584          + index[6] * stride_[6] + index[7] * stride_[7]
01585          + index[8] * stride_[8]];
01586     }
01587 
01588     const T_numtype& restrict operator()(const TinyVector<int,10>& index) const
01589     {
01590         assertInRange(index[0], index[1], index[2], index[3],
01591             index[4], index[5], index[6], index[7], index[8], index[9]);
01592         return data_[(index[0]) * stride_[0]
01593          + index[1] * stride_[1]
01594          + index[2] * stride_[2] + index[3] * stride_[3]
01595          + index[4] * stride_[4] + index[5] * stride_[5]
01596          + index[6] * stride_[6] + index[7] * stride_[7]
01597          + index[8] * stride_[8] + index[9] * stride_[9]];
01598     }
01599 
01600     T_numtype& operator()(const TinyVector<int,10>& index)
01601     {
01602         assertInRange(index[0], index[1], index[2], index[3],
01603             index[4], index[5], index[6], index[7], index[8], index[9]);
01604         return data_[(index[0]) * stride_[0]
01605          + index[1] * stride_[1]
01606          + index[2] * stride_[2] + index[3] * stride_[3]
01607          + index[4] * stride_[4] + index[5] * stride_[5]
01608          + index[6] * stride_[6] + index[7] * stride_[7]
01609          + index[8] * stride_[8] + index[9] * stride_[9]];
01610     }
01611 
01612     const T_numtype& restrict operator()(const TinyVector<int,11>& index) const
01613     {
01614         assertInRange(index[0], index[1], index[2], index[3],
01615             index[4], index[5], index[6], index[7], index[8], index[9],
01616             index[10]);
01617         return data_[(index[0]) * stride_[0] 
01618          + index[1] * stride_[1]
01619          + index[2] * stride_[2] + index[3] * stride_[3]
01620          + index[4] * stride_[4] + index[5] * stride_[5]
01621          + index[6] * stride_[6] + index[7] * stride_[7]
01622          + index[8] * stride_[8] + index[9] * stride_[9]
01623          + index[10] * stride_[10]];
01624     }
01625 
01626     T_numtype& operator()(const TinyVector<int,11>& index)
01627     {
01628         assertInRange(index[0], index[1], index[2], index[3],
01629             index[4], index[5], index[6], index[7], index[8], index[9],
01630             index[10]);
01631         return data_[(index[0]) * stride_[0]
01632          + index[1] * stride_[1]
01633          + index[2] * stride_[2] + index[3] * stride_[3]
01634          + index[4] * stride_[4] + index[5] * stride_[5]
01635          + index[6] * stride_[6] + index[7] * stride_[7]
01636          + index[8] * stride_[8] + index[9] * stride_[9]
01637          + index[10] * stride_[10]];
01638     }
01639 
01640     const T_numtype& restrict operator()(int i0) const
01641     { 
01642         assertInRange(i0);
01643         return data_[(i0) * stride_[0]]; 
01644     }
01645 
01646     T_numtype& restrict operator()(int i0) 
01647     {
01648         assertInRange(i0);
01649         return data_[(i0) * stride_[0]];
01650     }
01651 
01652     const T_numtype& restrict operator()(int i0, int i1) const
01653     { 
01654         assertInRange(i0, i1);
01655         return data_[(i0) * stride_[0] + i1 * stride_[1]];
01656     }
01657 
01658     T_numtype& restrict operator()(int i0, int i1)
01659     {
01660         assertInRange(i0, i1);
01661         return data_[(i0) * stride_[0] + i1 * stride_[1]];
01662     }
01663 
01664     const T_numtype& restrict operator()(int i0, int i1, int i2) const
01665     {
01666         assertInRange(i0, i1, i2);
01667         return data_[(i0) * stride_[0] + i1 * stride_[1]
01668          + i2 * stride_[2]];
01669     }
01670 
01671     T_numtype& restrict operator()(int i0, int i1, int i2) 
01672     {
01673         assertInRange(i0, i1, i2);
01674         return data_[(i0) * stride_[0] + i1 * stride_[1]
01675          + i2 * stride_[2]];
01676     }
01677 
01678     const T_numtype& restrict operator()(int i0, int i1, int i2, int i3) const
01679     {
01680         assertInRange(i0, i1, i2, i3);
01681         return data_[(i0) * stride_[0] + i1 * stride_[1]
01682          + i2 * stride_[2] + i3 * stride_[3]];
01683     }
01684 
01685     T_numtype& restrict operator()(int i0, int i1, int i2, int i3)
01686     {
01687         assertInRange(i0, i1, i2, i3);
01688         return data_[(i0) * stride_[0] + i1 * stride_[1]
01689          + i2 * stride_[2] + i3 * stride_[3]];
01690     }
01691 
01692     const T_numtype& restrict operator()(int i0, int i1, int i2, int i3,
01693         int i4) const
01694     {
01695         assertInRange(i0, i1, i2, i3, i4);
01696         return data_[(i0) * stride_[0] + i1 * stride_[1]
01697          + i2 * stride_[2] + i3 * stride_[3] + i4 * stride_[4]];
01698     }
01699 
01700     T_numtype& restrict operator()(int i0, int i1, int i2, int i3,
01701         int i4)
01702     {
01703         assertInRange(i0, i1, i2, i3, i4);
01704         return data_[(i0) * stride_[0] + i1 * stride_[1]
01705          + i2 * stride_[2] + i3 * stride_[3] + i4 * stride_[4]];
01706     }
01707 
01708     const T_numtype& restrict operator()(int i0, int i1, int i2, int i3,
01709         int i4, int i5) const
01710     {
01711         assertInRange(i0, i1, i2, i3, i4, i5);
01712         return data_[(i0) * stride_[0] + i1 * stride_[1]
01713          + i2 * stride_[2] + i3 * stride_[3] + i4 * stride_[4]
01714          + i5 * stride_[5]];
01715     }
01716 
01717     T_numtype& restrict operator()(int i0, int i1, int i2, int i3,
01718         int i4, int i5)
01719     {
01720         assertInRange(i0, i1, i2, i3, i4, i5);
01721         return data_[(i0) * stride_[0] + i1 * stride_[1]
01722             + i2 * stride_[2] + i3 * stride_[3] + i4 * stride_[4]
01723             + i5 * stride_[5]];
01724     }
01725 
01726     const T_numtype& restrict operator()(int i0, int i1, int i2, int i3,
01727         int i4, int i5, int i6) const
01728     {
01729         assertInRange(i0, i1, i2, i3, i4, i5, i6);
01730         return data_[(i0) * stride_[0] + i1 * stride_[1]
01731             + i2 * stride_[2] + i3 * stride_[3] + i4 * stride_[4]
01732             + i5 * stride_[5] + i6 * stride_[6]];
01733     }
01734 
01735     T_numtype& restrict operator()(int i0, int i1, int i2, int i3,
01736         int i4, int i5, int i6)
01737     {
01738         assertInRange(i0, i1, i2, i3, i4, i5, i6);
01739         return data_[(i0) * stride_[0] + i1 * stride_[1]
01740             + i2 * stride_[2] + i3 * stride_[3] + i4 * stride_[4]
01741             + i5 * stride_[5] + i6 * stride_[6]];
01742     }
01743 
01744     const T_numtype& restrict operator()(int i0, int i1, int i2, int i3,
01745         int i4, int i5, int i6, int i7) const
01746     {
01747         assertInRange(i0, i1, i2, i3, i4, i5, i6, i7);
01748         return data_[(i0) * stride_[0] + i1 * stride_[1]
01749             + i2 * stride_[2] + i3 * stride_[3] + i4 * stride_[4]
01750             + i5 * stride_[5] + i6 * stride_[6] + i7 * stride_[7]];
01751     }
01752 
01753     T_numtype& restrict operator()(int i0, int i1, int i2, int i3,
01754         int i4, int i5, int i6, int i7)
01755     {
01756         assertInRange(i0, i1, i2, i3, i4, i5, i6, i7);
01757         return data_[(i0) * stride_[0] + i1 * stride_[1]
01758             + i2 * stride_[2] + i3 * stride_[3] + i4 * stride_[4]
01759             + i5 * stride_[5] + i6 * stride_[6] + i7 * stride_[7]];
01760     }
01761 
01762     const T_numtype& restrict operator()(int i0, int i1, int i2, int i3,
01763         int i4, int i5, int i6, int i7, int i8) const
01764     {
01765         assertInRange(i0, i1, i2, i3, i4, i5, i6, i7, i8);
01766         return data_[(i0) * stride_[0] + i1 * stride_[1]
01767             + i2 * stride_[2] + i3 * stride_[3] + i4 * stride_[4]
01768             + i5 * stride_[5] + i6 * stride_[6] + i7 * stride_[7]
01769             + i8 * stride_[8]];
01770     }
01771 
01772     T_numtype& restrict operator()(int i0, int i1, int i2, int i3,
01773         int i4, int i5, int i6, int i7, int i8)
01774     {
01775         assertInRange(i0, i1, i2, i3, i4, i5, i6, i7, i8);
01776         return data_[(i0) * stride_[0] + i1 * stride_[1]
01777             + i2 * stride_[2] + i3 * stride_[3] + i4 * stride_[4]
01778             + i5 * stride_[5] + i6 * stride_[6] + i7 * stride_[7]
01779             + i8 * stride_[8]];
01780     }
01781 
01782     const T_numtype& restrict operator()(int i0, int i1, int i2, int i3,
01783         int i4, int i5, int i6, int i7, int i8, int i9) const
01784     {
01785         assertInRange(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9);
01786         return data_[(i0) * stride_[0] + i1 * stride_[1]
01787             + i2 * stride_[2] + i3 * stride_[3] + i4 * stride_[4]
01788             + i5 * stride_[5] + i6 * stride_[6] + i7 * stride_[7]
01789             + i8 * stride_[8] + i9 * stride_[9]];
01790     }
01791 
01792     T_numtype& restrict operator()(int i0, int i1, int i2, int i3,
01793         int i4, int i5, int i6, int i7, int i8, int i9)
01794     {
01795         assertInRange(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9);
01796         return data_[(i0) * stride_[0] + i1 * stride_[1]
01797             + i2 * stride_[2] + i3 * stride_[3] + i4 * stride_[4]
01798             + i5 * stride_[5] + i6 * stride_[6] + i7 * stride_[7]
01799             + i8 * stride_[8] + i9 * stride_[9]];
01800     }
01801 
01802     const T_numtype& restrict operator()(int i0, int i1, int i2, int i3,
01803         int i4, int i5, int i6, int i7, int i8, int i9, int i10) const
01804     {
01805         assertInRange(i0, i1, i2, i3, i4, i5, i6, i7, i8, 
01806             i9, i10);
01807         return data_[(i0) * stride_[0] + i1 * stride_[1]
01808             + i2 * stride_[2] + i3 * stride_[3] + i4 * stride_[4]
01809             + i5 * stride_[5] + i6 * stride_[6] + i7 * stride_[7]
01810             + i8 * stride_[8] + i9 * stride_[9] + i10 * stride_[10]];
01811     }
01812 
01813     T_numtype& restrict operator()(int i0, int i1, int i2, int i3,
01814         int i4, int i5, int i6, int i7, int i8, int i9, int i10)
01815     {
01816         assertInRange(i0, i1, i2, i3, i4, i5, i6, i7, i8, 
01817             i9, i10);
01818         return data_[(i0) * stride_[0] + i1 * stride_[1]
01819             + i2 * stride_[2] + i3 * stride_[3] + i4 * stride_[4]
01820             + i5 * stride_[5] + i6 * stride_[6] + i7 * stride_[7]
01821             + i8 * stride_[8] + i9 * stride_[9] + i10 * stride_[10]];
01822     }
01823 
01824     /*
01825      * Slicing to produce subarrays.  If the number of Range arguments is
01826      * fewer than N_rank, then missing arguments are treated like Range::all().
01827      */
01828 
01829     T_array& noConst() const
01830     { return const_cast<T_array&>(*this); }
01831 
01832     T_array operator()(const RectDomain<N_rank>& subdomain) const
01833     {
01834         return T_array(noConst(), subdomain);
01835     }
01836 
01837     /* Operator added by Julian Cummings */
01838     T_array operator()(const StridedDomain<N_rank>& subdomain) const
01839     {
01840         return T_array(noConst(), subdomain);
01841     }
01842 
01843     T_array operator()(Range r0) const
01844     {
01845         return T_array(noConst(), r0);
01846     }
01847 
01848     T_array operator()(Range r0, Range r1) const
01849     {
01850         return T_array(noConst(), r0, r1);
01851     }
01852 
01853     T_array operator()(Range r0, Range r1, Range r2) const
01854     {
01855         return T_array(noConst(), r0, r1, r2);
01856     }
01857 
01858     T_array operator()(Range r0, Range r1, Range r2, Range r3) const
01859     {
01860         return T_array(noConst(), r0, r1, r2, r3);
01861     }
01862 
01863     T_array operator()(Range r0, Range r1, Range r2, Range r3, Range r4) const
01864     {
01865         return T_array(noConst(), r0, r1, r2, r3, r4);
01866     }
01867 
01868     T_array operator()(Range r0, Range r1, Range r2, Range r3, Range r4,
01869         Range r5) const
01870     {
01871         return T_array(noConst(), r0, r1, r2, r3, r4, r5);
01872     }
01873 
01874     T_array operator()(Range r0, Range r1, Range r2, Range r3, Range r4,
01875         Range r5, Range r6) const
01876     {
01877         return T_array(noConst(), r0, r1, r2, r3, r4, r5, r6);
01878     }
01879 
01880     T_array operator()(Range r0, Range r1, Range r2, Range r3, Range r4,
01881         Range r5, Range r6, Range r7) const
01882     {
01883         return T_array(noConst(), r0, r1, r2, r3, r4, r5, r6, r7);
01884     }
01885 
01886     T_array operator()(Range r0, Range r1, Range r2, Range r3, Range r4,
01887         Range r5, Range r6, Range r7, Range r8) const
01888     {
01889         return T_array(noConst(), r0, r1, r2, r3, r4, r5, r6, r7, r8);
01890     }
01891 
01892     T_array operator()(Range r0, Range r1, Range r2, Range r3, Range r4,
01893         Range r5, Range r6, Range r7, Range r8, Range r9) const
01894     {
01895         return T_array(noConst(), r0, r1, r2, r3, r4, r5, r6, r7, r8, r9);
01896     }
01897 
01898     T_array operator()(Range r0, Range r1, Range r2, Range r3, Range r4,
01899         Range r5, Range r6, Range r7, Range r8, Range r9, Range r10) const
01900     {
01901         return T_array(noConst(), r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10);
01902     }
01903 
01904     // Allow any mixture of Range, int and Vector<int> objects as
01905     // operands for operator():   A(Range(3,7), 5, Range(2,4))
01906 
01907     /*
01908      * These versions of operator() allow any combination of int
01909      * and Range operands to be used.  Each int operand reduces
01910      * the rank of the resulting array by one.  
01911      *
01912      * e.g.  Array<int,4> A(20,20,20,20);
01913      *       Array<int,2> B = A(Range(5,15), 3, 5, Range(8,9));
01914      *
01915      * SliceInfo is a helper class defined in <blitz/arrayslice.h>.
01916      * It counts the number of Range vs. int arguments and does some
01917      * other helpful things.
01918      *
01919      * Once partial specialization becomes widely implemented, these
01920      * operators may be expanded to accept Vector<int> arguments
01921      * and produce ArrayPick<T,N> objects.
01922      *
01923      * This operator() is not provided with a single argument because
01924      * the appropriate cases exist above.
01925      */
01926 
01927 #ifdef BZ_HAVE_PARTIAL_ORDERING
01928 
01929     template<typename T1, typename T2>
01930     typename SliceInfo<T_numtype,T1,T2>::T_slice
01931     operator()(T1 r1, T2 r2) const
01932     {
01933         typedef typename SliceInfo<T_numtype,T1,T2>::T_slice slice;
01934         return slice(noConst(), r1, r2, nilArraySection(), nilArraySection(), nilArraySection(),
01935             nilArraySection(), nilArraySection(), nilArraySection(),
01936             nilArraySection(), nilArraySection(), nilArraySection());
01937     }
01938 
01939     template<typename T1, typename T2, typename T3>
01940     typename SliceInfo<T_numtype,T1,T2,T3>::T_slice 
01941     operator()(T1 r1, T2 r2, T3 r3) const
01942     {
01943         typedef typename SliceInfo<T_numtype,T1,T2,T3>::T_slice slice;
01944         return slice(noConst(), r1, r2, r3, nilArraySection(), nilArraySection(), nilArraySection(),
01945             nilArraySection(), nilArraySection(), nilArraySection(),
01946             nilArraySection(), nilArraySection());
01947     }
01948 
01949     template<typename T1, typename T2, typename T3, typename T4>
01950     typename SliceInfo<T_numtype,T1,T2,T3,T4>::T_slice
01951     operator()(T1 r1, T2 r2, T3 r3, T4 r4) const
01952     {
01953         typedef typename SliceInfo<T_numtype,T1,T2,T3,T4>::T_slice slice;
01954         return slice(noConst(), r1, r2, r3, r4, nilArraySection(), nilArraySection(),
01955             nilArraySection(), nilArraySection(), nilArraySection(),
01956             nilArraySection(), nilArraySection());
01957     }
01958 
01959     template<typename T1, typename T2, typename T3, typename T4, typename T5>
01960     typename SliceInfo<T_numtype,T1,T2,T3,T4,T5>::T_slice
01961     operator()(T1 r1, T2 r2, T3 r3, T4 r4, T5 r5) const
01962     {
01963         typedef typename SliceInfo<T_numtype,T1,T2,T3,T4,T5>::T_slice slice;
01964         return slice(noConst(), r1, r2, r3, r4, r5, nilArraySection(),
01965             nilArraySection(), nilArraySection(), nilArraySection(),
01966             nilArraySection(), nilArraySection());
01967     }
01968 
01969     template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
01970     typename SliceInfo<T_numtype,T1,T2,T3,T4,T5,T6>::T_slice
01971     operator()(T1 r1, T2 r2, T3 r3, T4 r4, T5 r5, T6 r6) const
01972     {
01973         typedef typename SliceInfo<T_numtype,T1,T2,T3,T4,T5,T6>::T_slice slice;
01974         return slice(noConst(), r1, r2, r3, r4, r5, r6, nilArraySection(), nilArraySection(), nilArraySection(),
01975             nilArraySection(), nilArraySection());
01976     }
01977 
01978     template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
01979         typename T7>
01980     typename SliceInfo<T_numtype,T1,T2,T3,T4,T5,T6,T7>::T_slice
01981     operator()(T1 r1, T2 r2, T3 r3, T4 r4, T5 r5, T6 r6, T7 r7) const
01982     {
01983         typedef typename SliceInfo<T_numtype,T1,T2,T3,T4,T5,T6,T7>::T_slice slice;
01984         return slice(noConst(), r1, r2, r3, r4, r5, r6, r7, nilArraySection(), nilArraySection(),
01985             nilArraySection(), nilArraySection());
01986     }
01987 
01988     template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
01989         typename T7, typename T8>
01990     typename SliceInfo<T_numtype,T1,T2,T3,T4,T5,T6,T7,T8>::T_slice
01991     operator()(T1 r1, T2 r2, T3 r3, T4 r4, T5 r5, T6 r6, T7 r7, T8 r8) const
01992     {
01993         typedef typename SliceInfo<T_numtype,T1,T2,T3,T4,T5,T6,T7,T8>::T_slice slice;
01994         return slice(noConst(), r1, r2, r3, r4, r5, r6, r7, r8,
01995             nilArraySection(), nilArraySection(), nilArraySection());
01996     }
01997 
01998     template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
01999         typename T7, typename T8, typename T9>
02000     typename SliceInfo<T_numtype,T1,T2,T3,T4,T5,T6,T7,T8,T9>::T_slice
02001     operator()(T1 r1, T2 r2, T3 r3, T4 r4, T5 r5, T6 r6, T7 r7, T8 r8, T9 r9) const
02002     {
02003         typedef typename SliceInfo<T_numtype,T1,T2,T3,T4,T5,T6,T7,T8,T9>::T_slice slice;
02004         return slice(noConst(), r1, r2, r3, r4, r5, r6, r7, r8, r9, nilArraySection(), nilArraySection());
02005     }
02006 
02007     template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
02008         typename T7, typename T8, typename T9, typename T10>
02009     typename SliceInfo<T_numtype,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10>::T_slice
02010     operator()(T1 r1, T2 r2, T3 r3, T4 r4, T5 r5, T6 r6, T7 r7, T8 r8, T9 r9, T10 r10) const
02011     {
02012         typedef typename SliceInfo<T_numtype,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10>::T_slice slice;
02013         return slice(noConst(), r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, nilArraySection());
02014     }
02015 
02016     template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
02017         typename T7, typename T8, typename T9, typename T10, typename T11>
02018     typename SliceInfo<T_numtype,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>::T_slice
02019     operator()(T1 r1, T2 r2, T3 r3, T4 r4, T5 r5, T6 r6, T7 r7, T8 r8, T9 r9, T10 r10, T11 r11) const
02020     {
02021         typedef typename SliceInfo<T_numtype,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>::T_slice slice;
02022         return slice(noConst(), r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11);
02023     }
02024 
02025 #endif // BZ_HAVE_PARTIAL_ORDERING
02026 
02027     /*
02028      * These versions of operator() are provided to support tensor-style
02029      * array notation, e.g.
02030      *
02031      * Array<float, 2> A, B;
02032      * firstIndex i;
02033      * secondIndex j;
02034      * thirdIndex k;
02035      * Array<float, 3> C = A(i,j) * B(j,k);
02036      */
02037 
02038     template<int N0>
02039     _bz_ArrayExpr<ArrayIndexMapping<FastArrayIterator<T_numtype, N_rank>, N0> >
02040     operator()(IndexPlaceholder<N0>) const
02041     { 
02042         return _bz_ArrayExpr<ArrayIndexMapping<FastArrayIterator<T_numtype, N_rank>, N0> >
02043             (noConst());
02044     }
02045 
02046     template<int N0, int N1>
02047     _bz_ArrayExpr<ArrayIndexMapping<FastArrayIterator<T_numtype, N_rank>, N0, N1> >
02048     operator()(IndexPlaceholder<N0>, IndexPlaceholder<N1>) const
02049     {
02050         return _bz_ArrayExpr<ArrayIndexMapping<FastArrayIterator<T_numtype, N_rank>, N0,
02051             N1> >(noConst());
02052     } 
02053 
02054     template<int N0, int N1, int N2>
02055     _bz_ArrayExpr<ArrayIndexMapping<FastArrayIterator<T_numtype, N_rank>, N0, N1, N2> >
02056     operator()(IndexPlaceholder<N0>, IndexPlaceholder<N1>,
02057         IndexPlaceholder<N2>) const
02058     {
02059         return _bz_ArrayExpr<ArrayIndexMapping<FastArrayIterator<T_numtype, N_rank>, N0,
02060             N1, N2> >(noConst());
02061     }
02062 
02063     template<int N0, int N1, int N2, int N3>
02064     _bz_ArrayExpr<ArrayIndexMapping<FastArrayIterator<T_numtype, N_rank>, N0, N1, N2, N3> >
02065     operator()(IndexPlaceholder<N0>, IndexPlaceholder<N1>,
02066         IndexPlaceholder<N2>, IndexPlaceholder<N3>) const
02067     {
02068         return _bz_ArrayExpr<ArrayIndexMapping<FastArrayIterator<T_numtype, N_rank>, N0,
02069             N1, N2, N3> >(noConst());
02070     }
02071 
02072     template<int N0, int N1, int N2, int N3, int N4>
02073     _bz_ArrayExpr<ArrayIndexMapping<FastArrayIterator<T_numtype, N_rank>, N0, N1, N2, N3, N4> >
02074     operator()(IndexPlaceholder<N0>, IndexPlaceholder<N1>,
02075         IndexPlaceholder<N2>, IndexPlaceholder<N3>, 
02076         IndexPlaceholder<N4>) const
02077     {
02078         return _bz_ArrayExpr<ArrayIndexMapping<FastArrayIterator<T_numtype, N_rank>, N0,
02079             N1, N2, N3, N4> >(noConst());
02080     }
02081 
02082     template<int N0, int N1, int N2, int N3, int N4, int N5>
02083     _bz_ArrayExpr<ArrayIndexMapping<FastArrayIterator<T_numtype, N_rank>, N0, N1, N2, N3, 
02084         N4, N5> >
02085     operator()(IndexPlaceholder<N0>, IndexPlaceholder<N1>,
02086         IndexPlaceholder<N2>, IndexPlaceholder<N3>, IndexPlaceholder<N4>,
02087         IndexPlaceholder<N5>) const
02088     {
02089         return _bz_ArrayExpr<ArrayIndexMapping<FastArrayIterator<T_numtype, N_rank>, N0,
02090             N1, N2, N3, N4, N5> >(noConst());
02091     }
02092 
02093     template<int N0, int N1, int N2, int N3, int N4, int N5, int N6>
02094     _bz_ArrayExpr<ArrayIndexMapping<FastArrayIterator<T_numtype, N_rank>, N0, N1, N2, N3,
02095         N4, N5, N6> >
02096     operator()(IndexPlaceholder<N0>, IndexPlaceholder<N1>,
02097         IndexPlaceholder<N2>, IndexPlaceholder<N3>, IndexPlaceholder<N4>,
02098         IndexPlaceholder<N5>, IndexPlaceholder<N6>) const
02099     {
02100         return _bz_ArrayExpr<ArrayIndexMapping<FastArrayIterator<T_numtype, N_rank>, N0,
02101             N1, N2, N3, N4, N5, N6> >(noConst());
02102     }
02103 
02104     template<int N0, int N1, int N2, int N3, int N4, int N5, int N6,
02105         int N7>
02106     _bz_ArrayExpr<ArrayIndexMapping<FastArrayIterator<T_numtype, N_rank>, N0, N1, N2, N3,
02107         N4, N5, N6, N7> >
02108     operator()(IndexPlaceholder<N0>, IndexPlaceholder<N1>,
02109         IndexPlaceholder<N2>, IndexPlaceholder<N3>, IndexPlaceholder<N4>,
02110         IndexPlaceholder<N5>, IndexPlaceholder<N6>, 
02111         IndexPlaceholder<N7>) const
02112     {
02113         return _bz_ArrayExpr<ArrayIndexMapping<FastArrayIterator<T_numtype, N_rank>, N0,
02114             N1, N2, N3, N4, N5, N6, N7> >(noConst());
02115     }
02116 
02117     template<int N0, int N1, int N2, int N3, int N4, int N5, int N6,
02118         int N7, int N8>
02119     _bz_ArrayExpr<ArrayIndexMapping<FastArrayIterator<T_numtype, N_rank>, N0, N1, N2, N3,
02120         N4, N5, N6, N7, N8> >
02121     operator()(IndexPlaceholder<N0>, IndexPlaceholder<N1>,
02122         IndexPlaceholder<N2>, IndexPlaceholder<N3>, IndexPlaceholder<N4>,
02123         IndexPlaceholder<N5>, IndexPlaceholder<N6>, IndexPlaceholder<N7>,
02124         IndexPlaceholder<N8>) const
02125     {
02126         return _bz_ArrayExpr<ArrayIndexMapping<FastArrayIterator<T_numtype, N_rank>, N0,
02127             N1, N2, N3, N4, N5, N6, N7, N8> >(noConst());
02128     }
02129 
02130     template<int N0, int N1, int N2, int N3, int N4, int N5, int N6,
02131         int N7, int N8, int N9>
02132     _bz_ArrayExpr<ArrayIndexMapping<FastArrayIterator<T_numtype, N_rank>, N0, N1, N2, N3,
02133         N4, N5, N6, N7, N8, N9> >
02134     operator()(IndexPlaceholder<N0>, IndexPlaceholder<N1>,
02135         IndexPlaceholder<N2>, IndexPlaceholder<N3>, IndexPlaceholder<N4>,
02136         IndexPlaceholder<N5>, IndexPlaceholder<N6>, IndexPlaceholder<N7>,
02137         IndexPlaceholder<N8>, IndexPlaceholder<N9>) const
02138     {
02139         return _bz_ArrayExpr<ArrayIndexMapping<FastArrayIterator<T_numtype, N_rank>, N0,
02140             N1, N2, N3, N4, N5, N6, N7, N8, N9> >(noConst());
02141     }
02142 
02143     template<int N0, int N1, int N2, int N3, int N4, int N5, int N6,
02144         int N7, int N8, int N9, int N10>
02145     _bz_ArrayExpr<ArrayIndexMapping<FastArrayIterator<T_numtype, N_rank>, N0, N1, N2, N3,
02146         N4, N5, N6, N7, N8, N9, N10> >
02147     operator()(IndexPlaceholder<N0>, IndexPlaceholder<N1>,
02148         IndexPlaceholder<N2>, IndexPlaceholder<N3>, IndexPlaceholder<N4>,
02149         IndexPlaceholder<N5>, IndexPlaceholder<N6>, IndexPlaceholder<N7>,
02150         IndexPlaceholder<N8>, IndexPlaceholder<N9>, 
02151         IndexPlaceholder<N10>) const
02152     {
02153         return _bz_ArrayExpr<ArrayIndexMapping<FastArrayIterator<T_numtype, N_rank>, N0,
02154             N1, N2, N3, N4, N5, N6, N7, N8, N9, N10> >(noConst());
02155     }
02156 
02158     // Support for multicomponent arrays
02160 
02161     /*
02162      * See <blitz/array/multi.h> for an explanation of the traits class
02163      * multicomponent_traits.
02164      */
02165 
02166     Array<typename multicomponent_traits<T_numtype>::T_element,N_rank>
02167     operator[](const unsigned component) {
02168         typedef typename multicomponent_traits<T_numtype>::T_element T_compType;
02169 
02170         return extractComponent(T_compType(),component,
02171                                 multicomponent_traits<T_numtype>::numComponents);
02172     }
02173 
02174     const Array<typename multicomponent_traits<T_numtype>::T_element,N_rank>
02175     operator[](const unsigned component) const {
02176         typedef typename multicomponent_traits<T_numtype>::T_element T_compType;
02177 
02178         return extractComponent(T_compType(),component,
02179                                 multicomponent_traits<T_numtype>::numComponents);
02180     }
02181 
02182     Array<typename multicomponent_traits<T_numtype>::T_element,N_rank>
02183     operator[](const int component) {
02184         return operator[](static_cast<unsigned>(component));
02185     }
02186 
02187     const Array<typename multicomponent_traits<T_numtype>::T_element,N_rank>
02188     operator[](const int component) const {
02189         return operator[](static_cast<unsigned>(component));
02190     }
02191 
02193     // Indirection
02195  
02196     template<typename T_indexContainer>
02197     IndirectArray<T_array, T_indexContainer>
02198     operator[](const T_indexContainer& index)
02199     {
02200         return IndirectArray<T_array, T_indexContainer>(*this,
02201             const_cast<T_indexContainer&>(index));
02202     }
02203  
02205     // Assignment Operators
02207 
02208     // Scalar operand
02209     // NEEDS_WORK : need a precondition check on
02210     // isStorageContiguous when operator, is used.
02211     ListInitializationSwitch<T_array,T_numtype*> operator=(T_numtype x)
02212     {
02213         return ListInitializationSwitch<T_array,T_numtype*>(*this, x);
02214     }
02215 
02216     T_array& initialize(T_numtype);
02217 
02218     // Was:
02219     // T_array& operator=(T_numtype);
02220 
02221 #ifdef BZ_NEW_EXPRESSION_TEMPLATES
02222     template<typename T_expr>
02223     T_array& operator=(const ETBase<T_expr>&);
02224     T_array& operator=(const Array<T_numtype,N_rank>&);
02225 
02226     template<typename T> T_array& operator+=(const T&);
02227     template<typename T> T_array& operator-=(const T&);
02228     template<typename T> T_array& operator*=(const T&);
02229     template<typename T> T_array& operator/=(const T&);
02230     template<typename T> T_array& operator%=(const T&);
02231     template<typename T> T_array& operator^=(const T&);
02232     template<typename T> T_array& operator&=(const T&);
02233     template<typename T> T_array& operator|=(const T&);
02234     template<typename T> T_array& operator>>=(const T&);
02235     template<typename T> T_array& operator<<=(const T&);
02236 
02237 #else
02238     T_array& operator+=(T_numtype);
02239     T_array& operator-=(T_numtype);
02240     T_array& operator*=(T_numtype);
02241     T_array& operator/=(T_numtype);
02242     T_array& operator%=(T_numtype);
02243     T_array& operator^=(T_numtype);
02244     T_array& operator&=(T_numtype);
02245     T_array& operator|=(T_numtype);
02246     T_array& operator>>=(T_numtype);
02247     T_array& operator<<=(T_numtype);
02248 
02249     // Array operands
02250     T_array& operator=(const Array<T_numtype,N_rank>&);
02251 
02252     template<typename P_numtype2> 
02253     T_array& operator=(const Array<P_numtype2,N_rank>&);
02254     template<typename P_numtype2>
02255     T_array& operator+=(const Array<P_numtype2,N_rank>&);
02256     template<typename P_numtype2>
02257     T_array& operator-=(const Array<P_numtype2,N_rank>&);
02258     template<typename P_numtype2>
02259     T_array& operator*=(const Array<P_numtype2,N_rank>&);
02260     template<typename P_numtype2>
02261     T_array& operator/=(const Array<P_numtype2,N_rank>&);
02262     template<typename P_numtype2>
02263     T_array& operator%=(const Array<P_numtype2,N_rank>&);
02264     template<typename P_numtype2>
02265     T_array& operator^=(const Array<P_numtype2,N_rank>&);
02266     template<typename P_numtype2>
02267     T_array& operator&=(const Array<P_numtype2,N_rank>&);
02268     template<typename P_numtype2>
02269     T_array& operator|=(const Array<P_numtype2,N_rank>&);
02270     template<typename P_numtype2>
02271     T_array& operator>>=(const Array<P_numtype2,N_rank>&);
02272     template<typename P_numtype2>
02273     T_array& operator<<=(const Array<P_numtype2,N_rank>&);
02274 
02275     // Array expression operands
02276     template<typename T_expr>
02277     inline T_array& operator=(BZ_ETPARM(_bz_ArrayExpr<T_expr>) expr);
02278     template<typename T_expr>
02279     inline T_array& operator+=(BZ_ETPARM(_bz_ArrayExpr<T_expr>) expr);
02280     template<typename T_expr>
02281     inline T_array& operator-=(BZ_ETPARM(_bz_ArrayExpr<T_expr>) expr);
02282     template<typename T_expr>
02283     inline T_array& operator*=(BZ_ETPARM(_bz_ArrayExpr<T_expr>) expr);
02284     template<typename T_expr>
02285     inline T_array& operator/=(BZ_ETPARM(_bz_ArrayExpr<T_expr>) expr);
02286     template<typename T_expr>
02287     inline T_array& operator%=(BZ_ETPARM(_bz_ArrayExpr<T_expr>) expr);
02288     template<typename T_expr>
02289     inline T_array& operator^=(BZ_ETPARM(_bz_ArrayExpr<T_expr>) expr);
02290     template<typename T_expr>
02291     inline T_array& operator&=(BZ_ETPARM(_bz_ArrayExpr<T_expr>) expr);
02292     template<typename T_expr>
02293     inline T_array& operator|=(BZ_ETPARM(_bz_ArrayExpr<T_expr>) expr);
02294     template<typename T_expr>
02295     inline T_array& operator>>=(BZ_ETPARM(_bz_ArrayExpr<T_expr>) expr);
02296     template<typename T_expr>
02297     inline T_array& operator<<=(BZ_ETPARM(_bz_ArrayExpr<T_expr>) expr);
02298 
02299     // NEEDS_WORK -- Index placeholder operand
02300 
02301     // NEEDS_WORK -- Random operand
02302 #endif
02303 
02304 public:
02305     // Undocumented implementation routines
02306 
02307     template<typename T_expr, typename T_update>
02308     inline T_array& evaluate(T_expr expr, T_update);
02309 
02310 #ifdef BZ_HAVE_STD
02311 #ifdef BZ_ARRAY_SPACE_FILLING_TRAVERSAL
02312     template<typename T_expr, typename T_update>
02313     inline T_array& evaluateWithFastTraversal(
02314         const TraversalOrder<N_rank - 1>& order, 
02315         T_expr expr, T_update);
02316 #endif // BZ_ARRAY_SPACE_FILLING_TRAVERSAL
02317 #endif
02318 
02319 #ifdef BZ_ARRAY_2D_STENCIL_TILING
02320     template<typename T_expr, typename T_update>
02321     inline T_array& evaluateWithTiled2DTraversal(
02322         T_expr expr, T_update);
02323 #endif
02324 
02325     template<typename T_expr, typename T_update>
02326     inline T_array& evaluateWithIndexTraversal1(
02327         T_expr expr, T_update);
02328 
02329     template<typename T_expr, typename T_update>
02330     inline T_array& evaluateWithIndexTraversalN(
02331         T_expr expr, T_update);
02332 
02333     template<typename T_expr, typename T_update>
02334     inline T_array& evaluateWithStackTraversal1(
02335         T_expr expr, T_update);
02336 
02337     template<typename T_expr, typename T_update>
02338     inline T_array& evaluateWithStackTraversalN(
02339         T_expr expr, T_update);
02340 
02341 
02342     T_numtype* restrict getInitializationIterator() { return dataFirst(); }
02343 
02344     bool canCollapse(int outerRank, int innerRank) const { 
02345 #ifdef BZ_DEBUG_TRAVERSE
02346         BZ_DEBUG_MESSAGE("stride(" << innerRank << ")=" << stride(innerRank)
02347           << ", extent()=" << extent(innerRank) << ", stride(outerRank)="
02348           << stride(outerRank));
02349 #endif
02350         return (stride(innerRank) * extent(innerRank) == stride(outerRank)); 
02351     }
02352 
02353 protected:
02355     // Implementation routines
02357 
02358     _bz_inline2 void computeStrides();
02359     _bz_inline2 void setupStorage(int rank);
02360     void constructSubarray(Array<T_numtype, N_rank>& array, 
02361         const RectDomain<N_rank>&);
02362     void constructSubarray(Array<T_numtype, N_rank>& array,
02363         const StridedDomain<N_rank>&);
02364     void constructSubarray(Array<T_numtype, N_rank>& array, Range r0);
02365     void constructSubarray(Array<T_numtype, N_rank>& array, Range r0, Range r1);
02366     void constructSubarray(Array<T_numtype, N_rank>& array, Range r0,
02367         Range r1, Range r2);
02368     void constructSubarray(Array<T_numtype, N_rank>& array, Range r0,
02369         Range r1, Range r2, Range r3);
02370     void constructSubarray(Array<T_numtype, N_rank>& array, Range r0,
02371         Range r1, Range r2, Range r3, Range r4);
02372     void constructSubarray(Array<T_numtype, N_rank>& array, Range r0,
02373         Range r1, Range r2, Range r3, Range r4, Range r5);
02374     void constructSubarray(Array<T_numtype, N_rank>& array, Range r0,
02375         Range r1, Range r2, Range r3, Range r4, Range r5, Range r6);
02376     void constructSubarray(Array<T_numtype, N_rank>& array, Range r0,
02377         Range r1, Range r2, Range r3, Range r4, Range r5, Range r6,
02378         Range r7);
02379     void constructSubarray(Array<T_numtype, N_rank>& array, Range r0,
02380         Range r1, Range r2, Range r3, Range r4, Range r5, Range r6,
02381         Range r7, Range r8);
02382     void constructSubarray(Array<T_numtype, N_rank>& array, Range r0,
02383         Range r1, Range r2, Range r3, Range r4, Range r5, Range r6,
02384         Range r7, Range r8, Range r9);
02385     void constructSubarray(Array<T_numtype, N_rank>& array, Range r0,
02386         Range r1, Range r2, Range r3, Range r4, Range r5, Range r6,
02387         Range r7, Range r8, Range r9, Range r10);
02388 
02389     void calculateZeroOffset();
02390 
02391     template<int N_rank2, typename R0, typename R1, typename R2, typename R3, typename R4, 
02392         typename R5, typename R6, typename R7, typename R8, typename R9, typename R10>
02393     void constructSlice(Array<T_numtype, N_rank2>& array, R0 r0, R1 r1, R2 r2, 
02394         R3 r3, R4 r4, R5 r5, R6 r6, R7 r7, R8 r8, R9 r9, R10 r10);
02395 
02396     template<int N_rank2>
02397     void slice(int& setRank, Range r, Array<T_numtype,N_rank2>& array,
02398         TinyVector<int,N_rank2>& rankMap, int sourceRank);
02399 
02400     template<int N_rank2>
02401     void slice(int& setRank, int i, Array<T_numtype,N_rank2>& array,
02402         TinyVector<int,N_rank2>& rankMap, int sourceRank);
02403 
02404     template<int N_rank2>
02405     void slice(int&, nilArraySection, Array<T_numtype,N_rank2>&,
02406         TinyVector<int,N_rank2>&, int)
02407     { }
02408 
02409     void doTranspose(int destRank, int sourceRank, T_array& array);
02410 
02411 protected:
02413     // Data members
02415 
02416     // NB: adding new data members may require changes to ctors, reference()
02417 
02418     /*
02419      * For a description of the storage_ members, see the comments for class 
02420      * GeneralArrayStorage<N_rank> above.
02421      *
02422      * length_[] contains the extent of each rank.  E.g. a 10x20x30 array
02423      *           would have length_ = { 10, 20, 30}.
02424      * stride_[] contains the stride to move to the next element along each
02425      *           rank.
02426      * zeroOffset_ is the distance from the first element in the array 
02427      *           to the point (0,0,...,0).  If base_ is zero and all ranks are 
02428      *           stored ascending, then zeroOffset_ is zero.  This value
02429      *           is needed because to speed up indexing, the data_ member
02430      *           (inherited from MemoryBlockReference) always refers to
02431      *           (0,0,...,0).
02432      */
02433     GeneralArrayStorage<N_rank> storage_;
02434     TinyVector<int, N_rank> length_;
02435     TinyVector<diffType, N_rank> stride_;
02436     diffType zeroOffset_;
02437 };
02438 
02439 /*
02440  * Rank numbers start with zero, which may be confusing to users coming
02441  * from Fortran.  To make code more readable, the following constants
02442  * may help.  Example: instead of
02443  * 
02444  * int firstRankExtent = A.extent(0);
02445  *
02446  * One can write:
02447  *
02448  * int firstRankExtent = A.extent(firstRank);
02449  */
02450 
02451 const int firstRank    = 0;
02452 const int secondRank   = 1;
02453 const int thirdRank    = 2;
02454 const int fourthRank   = 3;
02455 const int fifthRank    = 4;
02456 const int sixthRank    = 5;
02457 const int seventhRank  = 6;
02458 const int eighthRank   = 7;
02459 const int ninthRank    = 8;
02460 const int tenthRank    = 9;
02461 const int eleventhRank = 10;
02462 
02463 const int firstDim    = 0;
02464 const int secondDim   = 1;
02465 const int thirdDim    = 2;
02466 const int fourthDim   = 3;
02467 const int fifthDim    = 4;
02468 const int sixthDim    = 5;
02469 const int seventhDim  = 6;
02470 const int eighthDim   = 7;
02471 const int ninthDim    = 8;
02472 const int tenthDim    = 9;
02473 const int eleventhDim = 10;
02474 
02475 /*
02476  * Global Functions
02477  */
02478 
02479 template<typename T_numtype>
02480 ostream& operator<<(ostream&, const Array<T_numtype,1>&);
02481 
02482 template<typename T_numtype, int N_rank>
02483 ostream& operator<<(ostream&, const Array<T_numtype,N_rank>&);
02484 
02485 template<typename T_numtype, int N_rank>
02486 istream& operator>>(istream& is, Array<T_numtype,N_rank>& x);
02487 
02488 template <typename P_numtype,int N_rank>
02489 void swap(Array<P_numtype,N_rank>& a,Array<P_numtype,N_rank>& b) {
02490     Array<P_numtype,N_rank> c(a);
02491     a.reference(b);
02492     b.reference(c);
02493 }
02494 
02495 template <typename P_expr>
02496 void find(Array<TinyVector<int,P_expr::rank>,1>& indices,
02497           const _bz_ArrayExpr<P_expr>& expr) {
02498     find(indices,
02499          static_cast< Array<typename P_expr::T_numtype,P_expr::rank> >(expr));
02500 }
02501 
02502 template <typename P_numtype, int N_rank>
02503 void find(Array<TinyVector<int,N_rank>,1>& indices,
02504           const Array<P_numtype,N_rank>& exprVals) {
02505     indices.resize(exprVals.size());
02506     typename Array<P_numtype,N_rank>::const_iterator it, end = exprVals.end();
02507     int j=0; 
02508     for (it = exprVals.begin(); it != end; ++it)
02509         if (*it) 
02510             indices(j++) = it.position();
02511     if (j) 
02512         indices.resizeAndPreserve(j);
02513     else 
02514         indices.free();
02515     return;
02516 }
02517 
02518 
02519 BZ_NAMESPACE_END
02520 
02521 /*
02522  * Include implementations of the member functions and some additional
02523  * global functions.
02524  */
02525 
02526 #include <blitz/array/iter.h>       // Array iterators
02527 #include <blitz/array/fastiter.h>   // Fast Array iterators (for et)
02528 #include <blitz/array/expr.h>       // Array expression objects
02529 #include <blitz/array/methods.cc>   // Member functions
02530 #include <blitz/array/eval.cc>      // Array expression evaluation
02531 #include <blitz/array/ops.cc>       // Assignment operators
02532 #include <blitz/array/io.cc>        // Output formatting
02533 #include <blitz/array/et.h>         // Expression templates
02534 #include <blitz/array/reduce.h>     // Array reduction expression templates
02535 #include <blitz/array/interlace.cc> // Allocation of interlaced arrays
02536 #include <blitz/array/resize.cc>    // Array resize, resizeAndPreserve
02537 #include <blitz/array/slicing.cc>   // Slicing and subarrays
02538 #include <blitz/array/cycle.cc>     // Cycling arrays
02539 #include <blitz/array/complex.cc>   // Special support for complex arrays
02540 #include <blitz/array/zip.h>        // Zipping multicomponent types
02541 #include <blitz/array/where.h>      // where(X,Y,Z)
02542 #include <blitz/array/indirect.h>   // Indirection
02543 #include <blitz/array/stencils.h>   // Stencil objects
02544 
02545 #endif // BZ_ARRAY_H
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines