1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
|
bzsubsect(Default constructor)
bzindex(Array!default ctor)
bzverb(
Array();
Array(GeneralArrayStorage<N_rank> storage)
)
The default constructor creates a C-style array of zero size. Any attempt
to access data in the array may result in a run-time error, because there
isn't any data to access!
An optional argument specifies a storage order for the array.
Arrays created using the default constructor can subsequently be given
data by the tt(resize()), tt(resizeAndPreserve()), or tt(reference())
member functions.
bzsubsect(Creating an array from an expression)
bzverb(
Array(expression...)
)
You may create an array from an array expression. For example,
bzverb(
Array<float,2> A(4,3), B(4,3); // ...
Array<float,2> C(A*2.0+B);
)
This is an explicit constructor (it will not be used to
perform implicit type conversions). The newly constructed
array will have the same storage format as the arrays in
the expression. If arrays with different storage formats
appear in the expression, an error will result.
(In this case, you must first construct the array, then
assign the expression to it).
bzsubsect(Constructors which take extent parameters)
bzindex(Array!ctors with extent parameters)
bzverb(
Array(int extent1);
Array(int extent1, int extent2);
Array(int extent1, int extent2, int extent3);
...
Array(int extent1, int extent2, int extent3, ..., int extent11)
)
These constructors take arguments which specify the size of the
array to be constructed. You should provide as many arguments
as there are dimensions in the array.+footnote(If you provide
fewer than N_rank arguments, the missing arguments will be
filled in using the last provided argument. However, for
code clarity, it makes sense to provide all N_rank parameters.)
An optional last parameter specifies a storage format:
bzverb(
Array(int extent1, GeneralArrayStorage<N_rank> storage);
Array(int extent1, int extent2, GeneralArrayStorage<N_rank> storage);
...
)
For high-rank arrays, it may be convenient to use this constructor:
bzindex(Array!high-rank)
bzverb(\
Array(const TinyVector<int, N_rank>& extent);
Array(const TinyVector<int, N_rank>& extent,
GeneralArrayStorage<N_rank> storage);
)
The argument tt(extent) is a vector containing the extent (length) of
the array in each dimension. The optional second parameter indicates
a storage format. Note that you can construct tt(TinyVector<int,N>)
objects on the fly with the tt(shape(i1,i2,...)) global function. For
example, tt(Array<int,2> A(shape(3,5))) will create a 3x5 array.
A similar constructor lets you provide both a vector of base
index values (lbounds) and extents:
bzverb(\
Array(const TinyVector<int, N_rank>& lbound,
const TinyVector<int, N_rank>& extent);
Array(const TinyVector<int, N_rank>& lbound,
const TinyVector<int, N_rank>& extent,
GeneralArrayStorage<N_rank> storage);
)
The argument tt(lbound) is a vector containing the base index value
(or lbound) of the array in each dimension.
The argument tt(extent) is a vector containing the extent (length) of
the array in each dimension. The optional third parameter indicates
a storage format. As with the above constructor, you can use the
tt(shape(i1,i2,...)) global function to create the tt(lbound)
and tt(extent) parameters.
bzsubsect(Constructors with Range arguments)
bzindex(Array!ctor with Range args)
These constructors allow arbitrary bases (starting indices) to be set:
bzverb(\
Array(Range r1);
Array(Range r1, Range r2);
Array(Range r1, Range r2, Range r3);
...
Array(Range r1, Range r2, Range r3, ..., Range r11);
)
For example, this code:
bzverb(\
Array<int,2> A(Range(10,20), Range(20,30));
)
will create an 11x11 array whose indices are 10..20 and 20..30. An optional
last parameter provides a storage order:
bzverb(\
Array(Range r1, GeneralArrayStorage<N_rank> storage);
Array(Range r1, Range r2, GeneralArrayStorage<N_rank> storage);
...
)
bzsubsect(Referencing another array)
bzindex(Array!referencing another array)
This constructor makes a shared view of another array's data:
bzindex(Array!creating a reference of another array)
bzverb(\
Array(Array<T_numtype, N_rank>& array);
)
After this constructor is used, both tt(Array) objects refer to the
em(same data). Any changes made to one array will appear in the
other array. If you want to make a duplicate copy of an array,
use the tt(copy()) member function.
bzsubsect(Constructing an array from an expression)
Arrays may be constructed from expressions, which are described
in ref(array-expressions). The syntax is:
bzverb(\
Array(...array expression...);
)
For example, this code creates an array B which contains
the square roots of the elements in A:
bzverb(\
Array<float,2> A(N,N); // ...
Array<float,2> B(sqrt(A));
)
bzsubsect(Creating an array from pre-existing data)
bzindex(Array!creating from pre-existing data)
When creating an array using a pointer to already existing data,
you have three choices for how Blitz++ will handle the data. These
choices are enumerated by the enum type tt(preexistingMemoryPolicy):
bzindex(Array!creating a reference of another array)
bzverb(\
enum preexistingMemoryPolicy {
duplicateData,
deleteDataWhenDone,
neverDeleteData
};
)
bzindex(preexistingMemoryPolicy)
bzindex(duplicateData)
bzindex(deleteDataWhenDone)
bzindex(neverDeleteData)
If you choose tt(duplicateData), Blitz++ will create an array object
using a copy of the data you provide. If you choose
tt(deleteDataWhenDone), Blitz++ will not create a copy of the data;
and when no array objects refer to the data anymore, it will
deallocate the data using tt(delete []). Note that to use
tt(deleteDataWhenDone), your array data must have been allocated
using the C++ tt(new) operator -- for example, you cannot allocate
array data using Fortran or tt(malloc), then create a Blitz++ array
from it using the tt(deleteDataWhenDone) flag. The third option
is tt(neverDeleteData), which means that Blitz++ will not never
deallocate the array data. This means it
is your responsibility to determine when the array data is no
longer needed, and deallocate it. You should use this option
for memory which has not been allocated using the C++ tt(new)
operator.
These constructors create array objects from pre-existing data:
bzverb(\
Array(T_numtype* dataFirst, TinyVector<int, N_rank> shape,
preexistingMemoryPolicy deletePolicy);
Array(T_numtype* dataFirst, TinyVector<int, N_rank> shape,
preexistingMemoryPolicy deletePolicy,
GeneralArrayStorage<N_rank> storage);
)
The first argument is a pointer to the array data. It should point to
the element of the array which is stored first in memory. The second
argument indicates the shape of the array. You can create this argument
using the tt(shape()) function. For example:
bzverb(\
double data[] = { 1, 2, 3, 4 };
Array<double,2> A(data, shape(2,2), neverDeleteData); // Make a 2x2 array
)
bzindex(shape())
The tt(shape()) function takes N integer arguments and returns a
tt(TinyVector<int,N>).
By default, Blitz++ arrays are row-major. If you want to work with
data which is stored in column-major order (e.g. a Fortran array),
use the second version of the constructor:
bzindex(Array!creating from Fortran arrays)
bzverb(\
Array<double,2> B(data, shape(2,2), neverDeleteData,
FortranArray<2>());
)
This is a tad awkward, so Blitz++ provides the global
object tt(fortranArray) which will convert to an
instance of tt(GeneralArrayStorage<N_rank>):
bzverb(\
Array<double,2> B(data, shape(2,2), neverDeleteData, fortranArray);
)
Another version of this constructor allows you to pass an arbitrary
vector of strides:
bzverb(\
Array(T_numtype* _bz_restrict dataFirst, TinyVector<int, N_rank> shape,
TinyVector<int, N_rank> stride,
preexistingMemoryPolicy deletePolicy,
GeneralArrayStorage<N_rank> storage = GeneralArrayStorage<N_rank>())
)
bzsubsect(Interlacing arrays)
bzindex(Array!interlacing)
bzindex(interlaceArrays())
bzindex(allocateArrays())
For some platforms, it can be advantageous to store a set of arrays
interlaced together in memory. Blitz++ provides support for
this through the routines tt(interlaceArrays()) and tt(allocateArrays()).
An example:
bzverb(\
Array<int,2> A, B;
interlaceArrays(shape(10,10), A, B);
)
The first parameter of tt(interlaceArrays()) is the shape for the
arrays (10x10). The subsequent arguments are the set of arrays to
be interlaced together. Up to 11 arrays may be interlaced.
All arrays must store the same data type and be of the same
rank.
In the above example, storage is allocated so that
tt(A(0,0)) is followed immediately by tt(B(0,0)) in memory,
which is folloed by tt(A(0,1)) and tt(B(0,1)), and so on.
A related routine is tt(allocateArrays()), which has identical syntax:
bzverb(\
Array<int,2> A, B;
allocateArrays(shape(10,10), A, B);
)
Unlike tt(interlaceArrays()), which always interlaces the arrays,
the routine tt(allocateArrays()) may or may not interlace them,
depending on whether interlacing is considered advantageous for your
platform. If the tuning flag tt(BZ_INTERLACE_ARRAYS) is
defined in tt(<blitz/tuning.h>), then the arrays are
interlaced.
Note that the performance effects of interlacing are
unpredictable: in some situations it can be a benefit, and in
most others it can slow your code down substantially. You should
only use tt(interlaceArrays()) after
running some benchmarks to determine whether interlacing
is beneficial for your particular algorithm and architecture.
bzsubsect(A note about reference counting)
bzindex(Array!reference counting)
bzindex(reference counting)
Blitz++ arrays use reference counting. When you create a new array,
a memory block is allocated. The tt(Array) object acts like a handle
for this memory block. A memory block can be shared among multiple
tt(Array) objects -- for example, when you take subarrays and slices.
The memory block keeps track of how many tt(Array) objects are
referring to it. When a memory block is orphaned -- when no
tt(Array) objects are referring to it -- it automatically
deletes itself and frees the allocated memory.
|