casacore
Loading...
Searching...
No Matches
Array.h
Go to the documentation of this file.
1//# Array.h: A templated N-D Array class with zero origin
2//# Copyright (C) 1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2015
3//# Associated Universities, Inc. Washington DC, USA,
4//# National Astronomical Observatory of Japan
5//# 2-21-1, Osawa, Mitaka, Tokyo, 181-8588, Japan.
6//#
7//# This library is free software; you can redistribute it and/or modify it
8//# under the terms of the GNU Library General Public License as published by
9//# the Free Software Foundation; either version 2 of the License, or (at your
10//# option) any later version.
11//#
12//# This library is distributed in the hope that it will be useful, but WITHOUT
13//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
15//# License for more details.
16//#
17//# You should have received a copy of the GNU Library General Public License
18//# along with this library; if not, write to the Free Software Foundation,
19//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
20//#
21//# Correspondence concerning AIPS++ should be addressed as follows:
22//# Internet email: casa-feedback@nrao.edu.
23//# Postal address: AIPS++ Project Office
24//# National Radio Astronomy Observatory
25//# 520 Edgemont Road
26//# Charlottesville, VA 22903-2475 USA
27
28#ifndef CASA_ARRAY_2_H
29#define CASA_ARRAY_2_H
30
31//# Includes
32#include "ArrayBase.h"
33#include "ArrayError.h"
34#include "IPosition.h"
35#include "MaskLogiArrFwd.h"
36#include "Storage.h"
37
38#include <complex>
39#include <iterator>
40#include <initializer_list>
41#include <type_traits>
42
43namespace casacore { //#Begin casa namespace
44
45// <summary> A templated N-D %Array class with zero origin. </summary>
46
47// Array<T> is a templated, N-dimensional, %Array class. The origin is zero,
48// but by default indices are zero-based. This Array class is the
49// base class for the Vector, Matrix, and Cube subclasses.
50//
51// Indexing into the array, and positions in general, are given with IPosition
52// (essentially a vector of integers) objects. That is, an N-dimensional
53// array requires a length-N IPosition to define a position within the array.
54// Unlike C, indexing is done with (), not []. Also, the storage order
55// is the same as in FORTRAN, i.e. memory varies most rapidly with the first
56// index.
57// <srcblock>
58// // axisLengths = [1,2,3,4,5]
59// IPosition axisLengths(5, 1, 2, 3, 4, 5);
60// Array<int> ai(axisLengths); // ai is a 5 dimensional array of
61// // integers; indices are 0-based
62// // => ai.nelements() == 120
63// Array<int> ai2(axisLengths); // The first element is at index 0
64// IPosition zero(5); zero = 0; // [0,0,0,0,0]
65// //...
66// </srcblock>
67// Indexing into an N-dimensional array is relatively expensive. Normally
68// you will index into a Vector, Matrix, or Cube. These may be obtained from
69// an N-dimensional array by creating a reference, or by using an
70// ArrayIterator. The "shape" of the array is an IPosition which gives the
71// length of each axis.
72//
73// An Array may be standalone, or it may refer to another array, or to
74// part of another array (by refer we mean that if you change a pixel in
75// the current array, a pixel in the referred to array also changes, i.e.
76// they share underlying storage).
77// <note role=warning>
78// One way one array can reference another is through the copy
79// constructor. While this might be what you want, you should
80// probably use the reference() member function to make it explicit.
81// The copy constructor is used when arguments are passed by value;
82// normally functions should not pass Arrays by value, rather they
83// should pass a reference or a const reference. On the positive
84// side, returning an array from a function is efficient since no
85// copying need be done.
86// </note>
87//
88// Aside from the explicit reference() member function, a user will
89// most commonly encounter an array which references another array
90// when he takes an array slice (or section). A slice is a sub-region of
91// an array (which might also have a stride: every nth row, every mth column,
92// ...).
93// <srcblock>
94// IPosition lengths(3,10,20,30);
95// Array<int> ai(lengths); // A 10x20x30 cube
96// Cube<int> ci;
97// //...
98// ci.reference(ai1); // ci and ai now reference the same
99// // storage
100// ci(0,0,0) = 123; // Can use Cube indexing
101// ci.xyPlane(2) = 0; // and other member functions
102// IPosition zero(3,0,0,0);
103// assert(ai(zero) == 123); // true because ai, ci are references
104// //...
105// Array<int> subArray;
106// IPosition blc(3,0,0,0), trc(3,5,5,5);
107// subArray.reference(ai(blc, trc));
108// subArray = 10; // All of subArray, which is the
109// // subcube from 0,0,0 to 5,5,5 in
110// // ai, has the value 10.
111// </srcblock>
112// While the last example has an array slice referenced explicitly by another
113// array variable, normally the user will often only use the slice as
114// a temporary in an expresion, for example:
115// <srcblock>
116// Array<Complex> array;
117// IPosition blc, trc, offset;
118// //...
119// // Copy from one region of the array into another
120// array(blc, trc) = array(blc+offset, trc+offset);
121// </srcblock>
122//
123// The Array classes are intended to operate on relatively large
124// amounts of data. While they haven't been extensively tuned yet,
125// they are relatively efficient in terms of speed. Presently they
126// are not space efficient -- the overhead is about 15 words. While
127// this will be improved (probably to about 1/2 that), these array
128// classes are not appropriate for very large numbers of very small
129// arrays. The Block<T> class may be what you want in this circumstance.
130//
131// Element by element mathematical and logical operations are available
132// for arrays (defined in aips/ArrayMath.h and aips/ArrayLogical.h).
133// Because arithmetic and logical functions are split out, it is possible
134// to create an Array<T> (and hence Vector<T> etc) for any type T that has
135// a default constructor, assignment operator, and copy constructor. In
136// particular, Array<String> works.
137//
138// If compiled with the preprocessor symbol AIPS_DEBUG symbol, array
139// consistency ("invariants") will be checked in most member
140// functions, and indexing will be range-checked. This should not be
141// defined for production runs.
142//
143// <note role=tip>
144// Most of the data members and functions which are "protected" should
145// likely become "private".
146// </note>
147//
148// <todo asof="1999/12/30">
149// <li> Integrate into the Lattice hierarchy
150// <li> Factor out the common functions (shape etc) into a type-independent
151// base class.
152// </todo>
153
154template<typename T> class Array : public ArrayBase
155{
156public:
157 // Result has dimensionality of zero, and nelements is zero.
159
160 // Create an array of the given shape, i.e. after construction
161 // array.ndim() == shape.nelements() and array.shape() == shape.
162 // The origin of the Array is zero.
163 // Storage is allocated by <src>DefaultAllocator<T></src>.
164 // Without initPolicy parameter, the initialization of elements depends on type <src>T</src>.
165 // When <src>T</src> is a fundamental type like <src>int</src>, elements are NOT initialized.
166 // When <src>T</src> is a class type like <src>casacore::Complex</src> or <src>std::string</src>, elements are initialized.
167 // This inconsistent behavior confuses programmers and make it hard to write efficient and generic code using template.
168 // Especially when <src>T</src> is of type <src>Complex</src> or <src>DComplex</src> and it is unnecessary to initialize,
169 // provide initPolicy with value <src>NO_INIT</src> to skip the initialization.
170 // Therefore, it is strongly recommended to explicitly provide initPolicy parameter,
171 explicit Array(const IPosition &shape);
172
173 // Create an array of the given shape and initialize it with the
174 // initial value.
175 // Storage is allocated by <src>DefaultAllocator<T></src>.
176 Array(const IPosition &shape, const T &initialValue);
177
178 // This is a tag for the constructor that may be used to construct an uninitialized Array.
180
181 // Constructor to create an uninitialized array. This constructor can for example
182 // be called with:
183 // <srcblock>
184 // Array<int> a(shape, Array<int>::uninitialized);
185 // </srcblock>
187
188 // Construct a one-dimensional array from an initializer list.
189 // Example:
190 // <srcblock>
191 // Array<int> a({5, 6, 7, 8});
192 // </srcblock>
193 Array(std::initializer_list<T> list);
194
195 // After construction, this and other reference the same storage.
196 Array(const Array<T> &other);
197
198 // Source will be empty after this call.
199 Array(Array<T>&& source) noexcept;
200
201 // Create an Array of a given shape from a pointer.
202 // If <src>policy</src> is <src>COPY</src>, storage of a new copy is allocated by <src>DefaultAllocator<T></src>.
203 // If <src>policy</src> is <src>TAKE_OVER</src>, <src>storage</src> will be destructed and released by the specified allocator.
204 // <srcblock>
205 // FILE *fp = ...;
206 // typedef DefaultAllocator<int> Alloc;
207 // Alloc::type alloc;
208 // IPosition shape(1, 10);
209 // int *ptr = alloc.allocate(shape.product());
210 // size_t nread = fread(ptr, sizeof(int), shape.product(), fp);
211 // Array<int> ai(shape, ptr, TAKE_OVER);
212 // </srcblock>
213 Array(const IPosition &shape, T *storage, StorageInitPolicy policy = COPY);
214
215 // Create an Array of a given shape from a pointer. Because the pointer
216 // is const, a copy is always made.
217 // The copy is allocated by <src>DefaultAllocator<T></src>.
218 Array(const IPosition &shape, const T *storage);
219
220 // Construct an array from an iterator and a shape.
221 template<typename InputIterator>
222 Array(const IPosition &shape, InputIterator startIter);
223
224 // Frees up storage only if this array was the last reference to it.
225 virtual ~Array() noexcept;
226
227 // Make an empty array of the same template type.
228 virtual std::unique_ptr<ArrayBase> makeArray() const override;
229
230 // Assign the other array to this array.
231 // If the shapes mismatch, this array is resized.
232 // <group>
233 void assign (const Array<T>& other);
234
235 void assignBase (const ArrayBase& other, bool checkType=true) override;
236 // </group>
237
238 // Set every element of the array to "value." Also could use the
239 // assignment operator which assigns an array from a scalar.
240 void set(const T &value);
241
242 // Apply the function to every element of the array. This modifies
243 // the array in place.
244 // (TODO this version made the other versions of apply() redundant)
245 template<typename Callable>
246 void apply(Callable function);
247
248 // After invocation, this array and other reference the same storage. That
249 // is, modifying an element through one will show up in the other. The
250 // arrays appear to be identical; they have the same shape.
251 // <br>Please note that this function makes it possible to reference a
252 // const Array, thus effectively it makes a const Array non-const.
253 // Although this may seem undesirable at first sight, it is necessary to
254 // be able to make references to temporary Array objects, in particular to
255 // Array slices. Otherwise one first needs to use the copy constructor.
256 //# The const has been introduced on 2005-Mar-31 because of the hassle
257 //# involved in calling the copy ctor before reference.
258 virtual void reference(const Array<T> &other);
259
260 // Copy the values in other to this. If the array on the left hand
261 // side has no elements, then it is resized to be the same size as
262 // as the array on the right hand side. Otherwise, the arrays must
263 // conform (same shapes).
264 // <srcblock>
265 // IPosition shape(2,10,10); // some shape
266 // Array<double> ad(shape);
267 // //...
268 // Array<double> ad2; // N.B. ad2.nelements() == 0
269 // ad2 = ad; // ad2 resizes, then elements
270 // // are copied.
271 // shape = 20;
272 // Array<double> ad3(shape);
273 // ad3 = ad; // Error: arrays do not conform
274 // </srcblock>
275 // Note that the assign function can be used to assign a
276 // non-conforming array.
277 Array<T>& assign_conforming(const Array<T>& other)
278 {
279 return assign_conforming_implementation(other, std::is_copy_assignable<T>());
280 }
281
282 // Copy to this those values in marray whose corresponding elements
283 // in marray's mask are true.
284 // <thrown>
285 // <li> ArrayConformanceError
286 // </thrown>
287 //
289
290 // TODO we should change the semantics
292 { return assign_conforming(other); }
293
294 // Calls assign_conforming().
297
298 // The move operator takes the storage from the given array. After moving an
299 // Array, the source Array will be left empty.
301
302 // Set every element of this array to "value". In other words, a scalar
303 // behaves as if it were a constant conformant array.
305
306 // This makes a copy of the array and returns it. This can be
307 // useful for, e.g. making working copies of function arguments
308 // that you can write into.
309 // <srcblock>
310 // void someFunction(const Array<int> &arg)
311 // {
312 // Array<int> tmp(arg.copy());
313 // // ...
314 // }
315 // </srcblock>
316 // Note that since the copy constructor makes a reference, if we just
317 // created used to copy constructor, modifying "tmp" would also
318 // modify "arg". Clearly another alternative would simply be:
319 // <srcblock>
320 // void someFunction(const Array<int> &arg)
321 // {
322 // Array<int> tmp;
323 // tmp = arg;
324 // // ...
325 // }
326 // </srcblock>
327 // which likely would be simpler to understand. (Should copy()
328 // be deprecated and removed?)
329 //
330 // TODO deprecate
331 Array<T> copy() const;
332
333 // This function copies the matching part of from array to this array.
334 // The matching part is the part with the minimum size for each axis.
335 // E.g. if this array has shape [4,5,6] and from array has shape [7,3],
336 // the matching part has shape [4,3].
337 // <br>Note it is used by the resize function if
338 // <src>copyValues==true</src>.
339 void copyMatchingPart (const Array<T>& from);
340
341 // This ensures that this array does not reference any other storage.
342 // <note role=tip>
343 // When a section is taken of an array with non-unity strides,
344 // storage can be wasted if the array, which originally contained
345 // all the data, goes away. unique() also reclaims storage. This
346 // is an optimization users don't normally need to understand.
347 //
348 // <srcblock>
349 // IPosition shape(...), blc(...), trc(...), inc(...);
350 // Array<float> af(shape);
351 // inc = 2; // or anything > 1
352 // Array<float> aSection.reference(af(blc, trc, inc));
353 // af.reference(anotherArray);
354 // // aSection now references storage that has a stride
355 // // in it, but nothing else is. Storage is wasted.
356 // aSection.unique();
357 // </srcblock>
358 // </note>
359 void unique();
360
361 // Create an STL vector from an Array. The created vector is a linear
362 // representation of the Array memory. See
363 // <linkto class=Vector>Vector</linkto> for
364 // details of the operation and its reverse (i.e. creating a
365 // <src>Vector</src> from a <src>vector</src>), and for details of
366 // definition and instantiation.
367 // <group>
368 template <class U>
369 void tovector(std::vector<T, U>& out) const;
370 std::vector<T> tovector() const;
371 // </group>
372
373 // It is occasionally useful to have an array which access the same
374 // storage appear to have a different shape. For example,
375 // turning an N-dimensional array into a Vector.
376 // <br>When the array data are contiguous, the array can be reshaped
377 // to any form as long as the number of elements stays the same.
378 // When not contiguous, it is only possible to remove or add axes
379 // with length 1.
380 // <srcblock>
381 // IPosition squareShape(2,5,5);
382 // Array<float> square(squareShape);
383 // IPosition lineShape(1,25);
384 // Vector<float> line(square.reform(lineShape));
385 // // "square"'s storage may now be accessed through Vector "line"
386 // </srcblock>
388
389 // Having an array that can be reused without requiring reallocation can
390 // be useful for large arrays. The method reformOrResize permits this
391 // usage.
392 //
393 // The reformOrResize method first attempts to reform the matrix so that
394 // it reuses the existing storage for an array with a new shape. If the
395 // existing storage will not hold the new shape, then the method will
396 // resize the array when resizeIfNeeded is true; if a resize is needed and
397 // resizeIfNeeded is false, then an ArrayConformanceError is thrown. The
398 // copyDataIfNeeded parameter is passed to resize if resizing is performed.
399 // resizePercentage is the percent of additional storage to be addeed when
400 // a resize is performed; this allows the allocations to be amortized when
401 // the caller expects to be calling this method again in the future. The
402 // parameter is used to define an allocation shape which is larger than
403 // the newShape by increasing the last dimension by resizePercentage percent
404 // (i.e., lastDim = (lastDim * (100 + resizePercentage)) / 100). If
405 // resizePercentage <= 0 then resizing uses newShape as-is. Returns true
406 // if resizing (allocation) was performed.
407 //
408 // To truncate the array so that it no longer holds additional storage,
409 // use the resize method.
410 //
411 // Array may not be shared with another Array object during this call.
412 // Exception thrown if it is shared.
413
414 bool reformOrResize (const IPosition & newShape,
415 size_t resizePercentage = 0,
416 bool resizeIfNeeded = true);
417
418 // Use this method to extend or reduce the last dimension of an array. If
419 // sufficient excess capacity exists then the bookkeeping is adjusted to
420 // support the new shape. If insufficient storage exists then a new array
421 // is allocated (unless resizeIfNeeded is false; then an exception is thrown).
422 // If resizing is not required then the data remains untouched; if resizing
423 // is required then the data is copied into the new storage. The resizePercentage
424 // works the same as for reformOrResize (see above). This method never releases
425 // extra storage; use "resize" to do this. Array may not be sharing storage
426 // with another array at call time; an exception will be thrown if the array is shared.
427 // Returns true if the array was extension required a Array<T>::resize operation.
428
429 bool adjustLastAxis (const IPosition & newShape,
430 size_t resizePercentage = 0,
431 bool resizeIfNeeded = true);
432
433 // Returns the number of elements allocated. This value is >= to the value returned
434 // by size().
435
436 size_t capacity () const;
437
438 // These member functions remove degenerate (ie. length==1) axes from
439 // Arrays. Only axes greater than startingAxis are considered (normally
440 // one wants to remove trailing axes). The first two of these functions
441 // return an Array reference with axes removed. The latter two functions
442 // let this Array object reference the 'other' array with degenerated axes
443 // removed.
444 // <br>
445 // Unless throwIfError is false, an exception will be thrown if
446 // startingAxis exceeds the array's dimensionality.
447 // <br>
448 // The functions with argument <src>ignoreAxes</src> do
449 // not consider the axes given in that argument. In this way it can be
450 // achieved that degenerate axes are kept.
451 // <note role=caution> When the two functions returning <src>void</src>
452 // are invoked on a derived object (e.g. Matrix), an exception is
453 // thrown if removing the degenerate axes from other does not result
454 // in a correct number of axes.
455 // </note>
456 // <group>
457 Array<T> nonDegenerate(size_t startingAxis=0, bool throwIfError=true) const;
458 Array<T> nonDegenerate(const IPosition& ignoreAxes) const;
459 void nonDegenerate(const Array<T> &other, size_t startingAxis=0,
460 bool throwIfError=true);
461 void nonDegenerate(const Array<T> &other, const IPosition &ignoreAxes)
462 { doNonDegenerate (other, ignoreAxes); }
463 // </group>
464
465 // Remove degenerate axes from this Array object.
466 // Note it does not make sense to use these functions on a derived object
467 // like Matrix, because it is not possible to remove axes from them.
468 // <group>
469 void removeDegenerate(size_t startingAxis=0,
470 bool throwIfError=true);
471 void removeDegenerate(const IPosition &ignoreAxes);
472 // </group>
473
474 // This member function returns an Array reference with the specified
475 // number of extra axes, all of length one, appended to the end of the
476 // Array. Note that the <src>reform</src> function can also be
477 // used to add extra axes.
478 // <group>
479 const Array<T> addDegenerate(size_t numAxes) const;
480 Array<T> addDegenerate(size_t numAxes);
481 // </group>
482
483 // Make this array a different shape. If <src>copyValues==true</src>
484 // the old values are copied over to the new array.
485 // Copying is done on a per axis basis, thus a subsection with the
486 // minimum of the old and new shape is copied.
487 // <br>Resize without argument is equal to resize(IPosition()).
488 // <br>It is important to note that if multiple Array objects
489 // reference the same data storage, this Array object still references
490 // the same data storage as the other Array objects if the shape does
491 // not change. Otherwise this Array object references newly allocated
492 // storage, while the other Array objects still reference the existing
493 // data storage.
494 // <br>If you want to be sure that the data storage of this Array object
495 // is not referenced by other Array objects, the function unique should
496 // be called first.
497 // <group>
498 void resize();
499
500 void resize(const IPosition &newShape, bool copyValues=false) override;
501 // </group>
502
503 // Access a single element of the array. This is relatively
504 // expensive. Extensive indexing should be done through one
505 // of the Array specializations (Vector, Matrix, Cube).
506 // <group>
508 const T &operator()(const IPosition &) const;
509 // </group>
510
511 // Get a reference to an array section extending
512 // from start to end (inclusive).
513 // <group>
515 const IPosition &end);
516 const Array<T> operator()(const IPosition &start,
517 const IPosition &end) const;
518 // Along the ith axis, every inc[i]'th element is chosen.
520 const IPosition &end,
521 const IPosition &inc);
522 const Array<T> operator()(const IPosition &start,
523 const IPosition &end,
524 const IPosition &inc) const;
525 // </group>
526
527 // Get a reference to an array section using a Slicer.
528 // <group>
530 const Array<T> operator()(const Slicer&) const;
531 // </group>
532
533 // Get a reference to a section of an array.
534 // This is the same as operator(), but can be used in a type-agnostic way.
535 std::unique_ptr<ArrayBase> getSection (const Slicer&) const override;
536
537 // Get the subset given by the i-th value of the last axis. So for a cube
538 // it returns the i-th xy plane. For a Matrix it returns the i-th row.
539 // The returned array references the original array data; its dimensionality
540 // is one less. For a 1-dim array it still returns a 1-dim array.
541 // <note>This function should not be used in tight loops as it is (much)
542 // slower than iterating using begin() and end(), ArrayIter, or
543 // ArrayAccessor.</note>
544 Array<T> operator[] (size_t i) const;
545
546 // Get the diagonal of each matrix part in the full array.
547 // The matrices are taken using axes firstAxes and firstAxis+1.
548 // diag==0 is main diagonal; diag>0 above the main diagonal; diag<0 below.
549 Array<T> diagonals (size_t firstAxis=0, long long diag=0) const;
550
551 // The array is masked by the input LogicalArray.
552 // This mask must conform to the array.
553 // <group>
556 // </group>
557
558 // The array is masked by the input MaskedLogicalArray.
559 // The mask is effectively the AND of the internal LogicalArray
560 // and the internal mask of the MaskedLogicalArray.
561 // The MaskedLogicalArray must conform to the array.
562 // <group>
565 // </group>
566
567 // The number of references the underlying storage has assigned to it.
568 // It is 1 unless there are outstanding references to the storage (e.g.,
569 // through a slice). Normally you have no need to do this since the
570 // arrays handle all of the references for you.
571 // NB: Even when nrefs()==1, the array might be shared, because the
572 // the storage itself might be shared. Therefore, this function should
573 // not be used outside debugging.
574 // TODO make protected.
575 size_t nrefs() const;
576
577 // Check to see if the Array is consistent. This is about the same thing
578 // as checking for invariants. If AIPS_DEBUG is defined, this is invoked
579 // after construction and on entry to most member functions.
580 virtual bool ok() const override;
581
582 // Are the shapes identical?
583 // <group>
584 bool conform (const Array<T> &other) const
585 { return conform2(other); }
586 bool conform (const MaskedArray<T> &other) const;
587 // </group>
588
589 // Get a pointer to the beginning of the array.
590 // Note that the array may not be contiguous.
591 // <group>
592 T* data()
593 { return begin_p; }
594 const T* data() const
595 { return begin_p; }
596 // </group>
597
598 // Generally use of this should be shunned, except to use a FORTRAN routine
599 // or something similar. Because you can't know the state of the underlying
600 // data layout (in particular, if there are increments) sometimes the
601 // pointer returned will be to a copy, but often this won't be necessary.
602 // A boolean is returned which tells you if this is a copy (and hence the
603 // storage must be deleted). Note that if you don't do anything unusual,
604 // getStorage followed by freeStorage or putStorage will do the deletion
605 // for you (if required). e.g.:
606 // <srcblock>
607 // Array<int> a(shape); ...
608 // bool deleteIt; int *storage = a.getStorage(deleteIt);
609 // foo(storage, a.nelements()); a.puStorage(storage, deleteIt);
610 // // or a.freeStorage(storage, deleteIt) if a is const.
611 // </srcblock>
612 // NB: However, if you only use getStorage, you will have to delete the
613 // pointer yourself using freeStorage().
614 //
615 // It would probably be useful to have corresponding "copyin" "copyout"
616 // functions that used a user supplied buffer.
617 // Note that deleteIt is set in this function.
618 // <group>
619 T *getStorage(bool& deleteIt);
620 const T *getStorage(bool& deleteIt) const
621 {
622 // The cast is OK because the return pointer will be cast to const
623 return const_cast<Array<T>*>(this)->getStorage(deleteIt);
624 }
625 void *getVStorage(bool &deleteIt) override;
626 const void *getVStorage(bool &deleteIt) const override;
627 // </group>
628
629 // putStorage() is normally called after a call to getStorage() (cf).
630 // The "storage" pointer is set to zero.
631 void putStorage(T *&storage, bool deleteAndCopy);
632 void putVStorage(void *&storage, bool deleteAndCopy) override;
633
634 // If deleteIt is set, delete "storage". Normally freeStorage calls
635 // will follow calls to getStorage. The reason the pointer is "const"
636 // is because only const pointers are released from const arrays.
637 // The "storage" pointer is set to zero.
638 // TODO this function can not be const for stateful allocators
639 void freeStorage(const T *&storage, bool deleteIt) const;
640 void freeVStorage(const void *&storage, bool deleteIt) const override;
641
642 // Replace the data values with those in the pointer <src>storage</src>.
643 // The results are undefined if storage does not point at nelements() or
644 // more data elements. After takeStorage() is called, <src>nrefs()</src>
645 // is 1.
646 // <group>
647 // If <src>policy</src> is <src>COPY</src>, storage of a new copy is allocated by <src>allocator</src>.
648 // If <src>policy</src> is <src>TAKE_OVER</src>, <src>storage</src> will be destructed and released by <src>allocator</src>.
649 virtual void takeStorage(const IPosition &shape, T *storage,
650 StorageInitPolicy policy = COPY);
651
652 // Since the pointer is const, a copy is always taken.
653 // Storage of a new copy is allocated by the specified allocator.
654 virtual void takeStorage(const IPosition &shape, const T *storage);
655 // </group>
656
657
658 // Used to iterate through Arrays. Derived classes VectorIterator and
659 // MatrixIterator are probably more useful.
660 friend class ArrayIterator<T>;
661
662 // Create an ArrayIterator object of the correct type.
663 std::unique_ptr<ArrayPositionIterator> makeIterator(size_t byDim) const override;
664
665 // <group name=STL-iterator>
666 // See the function begin() and end() for a detailed description
667 // of the STL iterator capability.
668 class BaseIteratorSTL
670 public:
671 // Create the begin const_iterator object for an Array.
672 explicit BaseIteratorSTL (const Array<T>&);
673 // Create the end const_iterator object for an Array.
674 // It also acts as the default constructor.
675 explicit BaseIteratorSTL (const T* end = 0)
677 itsArray(0), itsContig(false) {}
678
679 void nextElem()
680 {
681 itsPos++;
682 if (!itsContig) {
684 if (itsPos > itsLineEnd) increment();
685 }
686 }
687 void nextLine()
688 {
690 increment();
691 }
692
693 bool operator== (const BaseIteratorSTL& other) const
694 { return itsPos == other.itsPos; }
695
696 bool operator!= (const BaseIteratorSTL& other) const
697 { return itsPos != other.itsPos; }
698
700 { return const_cast<T*>(itsPos); }
701
702 friend std::ostream& operator<< (std::ostream& os, const BaseIteratorSTL& iter)
703 { os << iter.itsPos; return os; }
704
705 protected:
706 // Increment iterator for a non-contiguous array.
707 void increment();
708
709 const T* itsPos;
710 const T* itsLineEnd;
717 };
718
720 {
721 public:
722 // <group name=STL-iterator-typedefs>
723 typedef T value_type;
726 typedef std::size_t size_type;
727 typedef ptrdiff_t difference_type;
728 typedef std::forward_iterator_tag iterator_category;
729 // </group>
730
731 // Create the begin iterator object for an Array.
732 explicit IteratorSTL (Array<T>& arr)
733 : BaseIteratorSTL (arr) {}
734 // Create the end iterator object for an Array.
735 // It also acts as the default constructor.
736 explicit IteratorSTL (const T* end = 0)
737 : BaseIteratorSTL (end) {}
738
740 {
741 this->nextElem();
742 return *this;
743 }
745 {
746 IteratorSTL old(*this);
747 this->nextElem();
748 return old;
749 }
750
752 { return *this->getPos(); }
754 { return this->getPos(); }
755 };
756
758 {
759 public:
760 // <group name=STL-const-iterator-typedefs>
761 typedef T value_type;
762 typedef const value_type* pointer;
763 typedef const value_type& reference;
764 typedef std::size_t size_type;
765 typedef ptrdiff_t difference_type;
766 typedef std::forward_iterator_tag iterator_category;
767 // </group>
768
769 // Create the begin const_iterator object for an Array.
770 explicit ConstIteratorSTL (const Array<T>& arr)
771 : BaseIteratorSTL (arr) {}
772 // Create the end const_iterator object for an Array.
773 // It also acts as the default constructor.
774 explicit ConstIteratorSTL (const T* end = 0)
775 : BaseIteratorSTL (end) {}
776 // Create from a non-const iterator.
778 : BaseIteratorSTL (iter) {}
779
781 {
782 this->nextElem();
783 return *this;
784 }
786 {
787 ConstIteratorSTL old(*this);
788 this->nextElem();
789 return old;
790 }
791
792 const T& operator*() const
793 { return *this->itsPos; }
794 const T* operator->()
795 { return this->itsPos; }
796
797 const T* pos() const
798 { return this->itsPos; }
799 };
800 // </group>
801
802 // Define the STL-style iterator functions (only forward iterator).
803 // It makes it possible to iterate through all data elements of an array
804 // and to use it common STL functions.
805 // The end() function is relatively expensive, so it should not be
806 // used inside a for statement. It is much better to call it beforehand
807 // as shown in the example below. Furthermore it is very important to
808 // use <src>++iter</src>, because <src>iter++</src> is 4 times slower.
809 // <srcblock>
810 // Array<int> arr(shape);
811 // Array<int>::iterator iterend(arr.end());
812 // for (Array<int>::iterator iter=arr.begin(); iter!=iterend; ++iter) {
813 // *iter += 1;
814 // }
815 // </srcblock>
816 // The Array class supports random access, so in principle a random
817 // iterator could be implemented, but its performance would not be great,
818 // especially for non-contiguous arrays.
819 // <br>Some other STL like functions exist for performance reasons.
820 // If the array is contiguous, it is possible to use the
821 // <src>cbegin</src> and <src>cend</src> functions which are
822 // about 10% faster.
823 // <group name=iterator-typedefs>
824 // STL-style typedefs.
825 // <group>
826
827 // Element type
828 typedef T value_type;
829 // TODO This is how std containers define a reference type, but
830 // the name 'reference' is already taken by a method.
831 // typedef T& reference;
832 typedef const T& const_reference;
833 // Pointer to an element type
834 typedef T* pointer;
835 // Constant pointer to the element type
836 typedef const T* const_pointer;
839 typedef T* contiter;
840 typedef const T* const_contiter;
841 // </group>
842 // Get the begin iterator object for any array.
843 // <group>
845 { return iterator (*this); }
847 { return const_iterator (*this); }
849 { return iterator(end_p); }
851 { return const_iterator(end_p); }
852 // </group>
853
854 // Get the begin iterator object for a contiguous array.
855 // <group>
857 { return begin_p; }
859 { return begin_p; }
861 { return end_p; }
863 { return end_p; }
864 // </group>
865
866 // </group>
867
868
869private:
870 // Implementation of constructor taking a Shape, a Templated parameter and an allocator.
871 // This method implements it for when T is integral, in which case the templated parameter
872 // is the initial value.
873 template<typename Integral>
874 Array(const IPosition &shape, Integral startIter, std::true_type /*is_integral*/ );
875
876 // Implementation of constructor taking a Shape, a Templated parameter and an allocator.
877 // This method implements it for when T is NOT integral, in which case the templated parameter
878 // is an iterator.
879 template<typename InputIterator>
880 Array(const IPosition &shape, InputIterator startIter, std::false_type /*is_integral*/ );
881
882 // Implementation for assign for copyable types
883 Array<T>& assign_conforming_implementation (const Array<T>& other, std::true_type);
884 // Implementation for assign for non-copyable types: can not be assigned
886 {
887 throw ArrayError("Can not assign from non-copyable object");
888 }
889 static void copyToContiguousStorage(T *dst, Array<T> const& src, std::true_type);
890 static void copyToContiguousStorage(T*, Array<T> const&, std::false_type)
891 {
892 throw ArrayError("Can not coy from non-copyable object");
893 }
894
895 // An Array is unique when the container is shared and when nrefs==1.
896 bool isUnique() const
897 {
898 return !data_p->is_shared() && nrefs()==1;
899 }
900
901protected:
902 // Source will be empty with given shape after this call.
903 Array(Array<T>&& source, const IPosition& shapeForSource) noexcept;
904
905 template<typename ST>
906 friend void swap(Array<ST>& left, Array<ST>& right);
907
908 // Swap this array with another array.
909 // Normally, casacore::swap() should be used instead.
910 void swap(Array<T>& other);
911
912 // pre/post processing hook of takeStorage() for subclasses.
913 virtual void preTakeStorage(const IPosition &) {}
914
915 virtual void postTakeStorage() {}
916
917 // This function is called when this array is about to be resized, before
918 // any work is done. Subclasses can throw an exception if the size doesn't
919 // match, e.g. if a Matrix is resized to have 3 dimensions.
920 // Before this function existed, assign-like functions had to be virtual.
921 // However, for non-copyable types, assign can't exist. This is fine for
922 // non-virtual methods (they just can't be called), but virtual methods
923 // cause the who class to fail to be instantiatable.
924 void checkBeforeResize(const IPosition &newShape)
925 {
926 if(fixedDimensionality() !=0 && newShape.size() != fixedDimensionality())
927 throw(ArrayNDimError(fixedDimensionality(), newShape.size(),
928 std::string("Invalid size given to ") + typeid(*this).name() +
929 ": should have dimensionality of " + std::to_string(fixedDimensionality())));
930 }
931
932 // Subclasses can return their dimensionality. The Array class will make sure
933 // that whenever it is resized, the dimensionality is checked.
934 // Array's constructors do not check the dimensionality, because the subclass
935 // hasn't been created yet at that point. Subclasses should therefore make
936 // sure to call the constructors appropriately.
937 // For classes that return 0, any resize will be allowed.
938 virtual size_t fixedDimensionality() const { return 0; }
939
940 virtual void checkAssignableType(ArrayBase& arrayBase) const
941 {
942 const Array<T>* pa = dynamic_cast<const Array<T>*>(&arrayBase);
943 if (pa == nullptr) {
944 throw ArrayError("ArrayBase& has incorrect template type");
945 }
946 }
947
948 static void copyToContiguousStorage(T *dst, Array<T> const& src)
949 {
950 copyToContiguousStorage(dst, src, std::is_copy_assignable<T>());
951 }
952
953 // Remove the degenerate axes from the Array object.
954 // This is the implementation of the nonDegenerate functions.
955 // It has a different name to be able to make it virtual without having
956 // the "hide virtual function" message when compiling derived classes.
957 virtual void doNonDegenerate(const Array<T> &other,
958 const IPosition &ignoreAxes);
959
960
961 // Shared pointer to a Storage that contains the data.
962 std::shared_ptr<arrays_internal::Storage<T>> data_p;
963
964 // This pointer is adjusted to point to the first element of the array.
965 // It is not necessarily the same thing as data->storage() since
966 // this array might be a section, e.g. have a blc which shifts us forward
967 // into the block.
969
970 // The end for an STL-style iteration.
972
973
974 // Fill the steps and the end for a derived class.
976 { baseMakeSteps(); this->setEndIter(); }
977
978 // Set the end iterator.
980 { end_p = (nels_p==0 ? 0 : (contiguous_p ? begin_p + nels_p :
981 begin_p + size_t(length_p(ndim()-1)) * steps_p(ndim()-1))); }
982};
983
984// Swap the first array with the second.
985// This is more efficient than std::swap()
986template<typename T>
988{
989 first.swap(second);
990}
991
992//# Declare extern templates for often used types.
993extern template class Array<bool>;
994extern template class Array<char>;
995extern template class Array<unsigned char>;
996extern template class Array<short>;
997extern template class Array<unsigned short>;
998extern template class Array<int>;
999extern template class Array<long long>;
1000extern template class Array<float>;
1001extern template class Array<double>;
1002
1003}//#End casa namespace
1004
1005#include "ArrayStr.h"
1006#include "Array.tcc"
1007
1008#endif
Non-templated base class for templated Array class.
Definition ArrayBase.h:71
size_t ndim() const
The dimensionality of this array.
Definition ArrayBase.h:96
size_t nels_p
Number of elements in the array.
Definition ArrayBase.h:267
bool contiguous_p
Are the data contiguous?
Definition ArrayBase.h:271
void baseMakeSteps()
Make the indexing step sizes.
const IPosition & shape() const
The length of each axis.
Definition ArrayBase.h:123
IPosition length_p
Used to hold the shape, increment into the underlying storage and originalLength of the array.
Definition ArrayBase.h:274
IPosition steps_p
Used to hold the step to next element in each dimension.
Definition ArrayBase.h:276
bool conform2(const ArrayBase &other) const
Are the shapes identical?
Definition ArrayBase.h:245
Thrown when two arrays have different dimensionality.
Definition ArrayError.h:133
bool operator==(const BaseIteratorSTL &other) const
Definition Array.h:693
const Array< T > * itsArray
Definition Array.h:715
BaseIteratorSTL(const T *end=0)
Create the end const_iterator object for an Array.
Definition Array.h:676
void increment()
Increment iterator for a non-contiguous array.
bool operator!=(const BaseIteratorSTL &other) const
Definition Array.h:696
friend std::ostream & operator<<(std::ostream &os, const BaseIteratorSTL &iter)
Definition Array.h:702
BaseIteratorSTL(const Array< T > &)
Create the begin const_iterator object for an Array.
std::forward_iterator_tag iterator_category
Definition Array.h:767
const value_type * pointer
Definition Array.h:763
ConstIteratorSTL operator++(int)
Definition Array.h:785
const ConstIteratorSTL & operator++()
Definition Array.h:780
ConstIteratorSTL(const Array< T > &arr)
Create the begin const_iterator object for an Array.
Definition Array.h:770
const value_type & reference
Definition Array.h:764
ConstIteratorSTL(const IteratorSTL &iter)
Create from a non-const iterator.
Definition Array.h:777
ConstIteratorSTL(const T *end=0)
Create the end const_iterator object for an Array.
Definition Array.h:774
const T & operator*() const
Definition Array.h:792
const IteratorSTL & operator++()
Definition Array.h:739
IteratorSTL operator++(int)
Definition Array.h:744
IteratorSTL(Array< T > &arr)
Create the begin iterator object for an Array.
Definition Array.h:732
std::forward_iterator_tag iterator_category
Definition Array.h:729
IteratorSTL(const T *end=0)
Create the end iterator object for an Array.
Definition Array.h:736
IteratorSTL iterator
Definition Array.h:837
Array< T > operator()(const IPosition &start, const IPosition &end)
Get a reference to an array section extending from start to end (inclusive).
static void copyToContiguousStorage(T *, Array< T > const &, std::false_type)
Definition Array.h:890
void resize(const IPosition &newShape, bool copyValues=false) override
Resize the array and optionally copy the values.
virtual void preTakeStorage(const IPosition &)
pre/post processing hook of takeStorage() for subclasses.
Definition Array.h:913
void assign(const Array< T > &other)
Assign the other array to this array.
void freeVStorage(const void *&storage, bool deleteIt) const override
Array(const IPosition &shape, const T *storage)
Create an Array of a given shape from a pointer.
Array(const IPosition &shape, T *storage, StorageInitPolicy policy=COPY)
Create an Array of a given shape from a pointer.
T * data()
Get a pointer to the beginning of the array.
Definition Array.h:592
size_t nrefs() const
The number of references the underlying storage has assigned to it.
bool adjustLastAxis(const IPosition &newShape, size_t resizePercentage=0, bool resizeIfNeeded=true)
Use this method to extend or reduce the last dimension of an array.
std::shared_ptr< arrays_internal::Storage< T > > data_p
Shared pointer to a Storage that contains the data.
Definition Array.h:962
Array(std::initializer_list< T > list)
Construct a one-dimensional array from an initializer list.
Array< T > & operator=(const Array< T > &other)
TODO we should change the semantics.
Definition Array.h:291
Array(const IPosition &shape, InputIterator startIter, std::false_type)
Implementation of constructor taking a Shape, a Templated parameter and an allocator.
T * begin_p
This pointer is adjusted to point to the first element of the array.
Definition Array.h:968
const Array< T > operator()(const IPosition &start, const IPosition &end) const
iterator begin()
Get the begin iterator object for any array.
Definition Array.h:844
const T * const_contiter
Definition Array.h:840
contiter cend()
Definition Array.h:860
void unique()
This ensures that this array does not reference any other storage.
void putVStorage(void *&storage, bool deleteAndCopy) override
Array< T > & assign_conforming(const MaskedArray< T > &marray)
Copy to this those values in marray whose corresponding elements in marray's mask are true.
T & operator()(const IPosition &)
Access a single element of the array.
ConstIteratorSTL const_iterator
Definition Array.h:838
Array(const IPosition &shape, uninitializedType)
Constructor to create an uninitialized array.
contiter cbegin()
Get the begin iterator object for a contiguous array.
Definition Array.h:856
Array(const IPosition &shape, const T &initialValue)
Create an array of the given shape and initialize it with the initial value.
void freeStorage(const T *&storage, bool deleteIt) const
If deleteIt is set, delete "storage".
Array< T > & operator=(Array< T > &&other)
The move operator takes the storage from the given array.
const T & const_reference
TODO This is how std containers define a reference type, but the name 'reference' is already taken by...
Definition Array.h:832
virtual void postTakeStorage()
Definition Array.h:915
Array< T > operator[](size_t i) const
Get the subset given by the i-th value of the last axis.
friend void swap(Array< ST > &left, Array< ST > &right)
bool isUnique() const
An Array is unique when the container is shared and when nrefs==1.
Definition Array.h:896
void makeSteps()
Fill the steps and the end for a derived class.
Definition Array.h:975
const T * const_pointer
Constant pointer to the element type.
Definition Array.h:836
Array< T > diagonals(size_t firstAxis=0, long long diag=0) const
Get the diagonal of each matrix part in the full array.
static void copyToContiguousStorage(T *dst, Array< T > const &src)
Definition Array.h:948
Array< T > nonDegenerate(const IPosition &ignoreAxes) const
Array(const IPosition &shape, InputIterator startIter)
Construct an array from an iterator and a shape.
void checkBeforeResize(const IPosition &newShape)
This function is called when this array is about to be resized, before any work is done.
Definition Array.h:924
const T * data() const
Definition Array.h:594
Array< T > & assign_conforming_implementation(const Array< T > &, std::false_type)
Implementation for assign for non-copyable types: can not be assigned.
Definition Array.h:885
void nonDegenerate(const Array< T > &other, const IPosition &ignoreAxes)
Definition Array.h:461
Array< T > copy() const
This makes a copy of the array and returns it.
const T & operator()(const IPosition &) const
void * getVStorage(bool &deleteIt) override
The following functions behave the same as the corresponding getStorage functions in the derived temp...
virtual std::unique_ptr< ArrayBase > makeArray() const override
Make an empty array of the same template type.
const_iterator begin() const
Definition Array.h:846
const_contiter cbegin() const
Definition Array.h:858
Array< T > & assign_conforming(const Array< T > &other)
Copy the values in other to this.
Definition Array.h:277
virtual void doNonDegenerate(const Array< T > &other, const IPosition &ignoreAxes)
Remove the degenerate axes from the Array object.
void removeDegenerate(const IPosition &ignoreAxes)
Array< T > operator()(const IPosition &start, const IPosition &end, const IPosition &inc)
Along the ith axis, every inc[i]'th element is chosen.
Array< T > & operator=(const MaskedArray< T > &marray)
Calls assign_conforming().
Definition Array.h:295
const_iterator end() const
Definition Array.h:850
virtual bool ok() const override
Check to see if the Array is consistent.
Array< T > operator()(const Slicer &)
Get a reference to an array section using a Slicer.
void setEndIter()
Set the end iterator.
Definition Array.h:979
Array(Array< T > &&source) noexcept
Source will be empty after this call.
T * pointer
Pointer to an element type.
Definition Array.h:834
virtual size_t fixedDimensionality() const
Subclasses can return their dimensionality.
Definition Array.h:938
const Array< T > operator()(const IPosition &start, const IPosition &end, const IPosition &inc) const
bool conform(const Array< T > &other) const
Are the shapes identical?
Definition Array.h:584
void tovector(std::vector< T, U > &out) const
Create an STL vector from an Array.
Array(Array< T > &&source, const IPosition &shapeForSource) noexcept
Source will be empty with given shape after this call.
Array< T > & assign_conforming_implementation(const Array< T > &other, std::true_type)
Implementation for assign for copyable types.
void nonDegenerate(const Array< T > &other, size_t startingAxis=0, bool throwIfError=true)
const_contiter cend() const
Definition Array.h:862
void resize()
Make this array a different shape.
std::unique_ptr< ArrayPositionIterator > makeIterator(size_t byDim) const override
Create an ArrayIterator object of the correct type.
Array(const Array< T > &other)
After construction, this and other reference the same storage.
static struct casacore::Array::uninitializedType uninitialized
const Array< T > addDegenerate(size_t numAxes) const
This member function returns an Array reference with the specified number of extra axes,...
Array< T > addDegenerate(size_t numAxes)
virtual ~Array() noexcept
Frees up storage only if this array was the last reference to it.
Array< T > nonDegenerate(size_t startingAxis=0, bool throwIfError=true) const
These member functions remove degenerate (ie.
void swap(Array< T > &other)
Swap this array with another array.
bool conform(const MaskedArray< T > &other) const
virtual void takeStorage(const IPosition &shape, T *storage, StorageInitPolicy policy=COPY)
Replace the data values with those in the pointer storage.
Array< T > & operator=(const T &value)
Set every element of this array to "value".
Array(const IPosition &shape)
Create an array of the given shape, i.e.
void copyMatchingPart(const Array< T > &from)
This function copies the matching part of from array to this array.
iterator end()
Definition Array.h:848
void removeDegenerate(size_t startingAxis=0, bool throwIfError=true)
Remove degenerate axes from this Array object.
virtual void checkAssignableType(ArrayBase &arrayBase) const
Definition Array.h:940
void putStorage(T *&storage, bool deleteAndCopy)
putStorage() is normally called after a call to getStorage() (cf).
const Array< T > operator()(const Slicer &) const
void set(const T &value)
Set every element of the array to "value." Also could use the assignment operator which assigns an ar...
virtual void reference(const Array< T > &other)
After invocation, this array and other reference the same storage.
std::unique_ptr< ArrayBase > getSection(const Slicer &) const override
Get a reference to a section of an array.
void apply(Callable function)
Apply the function to every element of the array.
bool reformOrResize(const IPosition &newShape, size_t resizePercentage=0, bool resizeIfNeeded=true)
Having an array that can be reused without requiring reallocation can be useful for large arrays.
Array()
Result has dimensionality of zero, and nelements is zero.
Array(const IPosition &shape, Integral startIter, std::true_type)
Implementation of constructor taking a Shape, a Templated parameter and an allocator.
T * end_p
The end for an STL-style iteration.
Definition Array.h:971
const T * getStorage(bool &deleteIt) const
Definition Array.h:620
std::vector< T > tovector() const
const void * getVStorage(bool &deleteIt) const override
size_t capacity() const
Returns the number of elements allocated.
T value_type
Define the STL-style iterator functions (only forward iterator).
Definition Array.h:828
void assignBase(const ArrayBase &other, bool checkType=true) override
Assign the source array to this array.
static void copyToContiguousStorage(T *dst, Array< T > const &src, std::true_type)
Array< T > reform(const IPosition &shape) const
It is occasionally useful to have an array which access the same storage appear to have a different s...
T * getStorage(bool &deleteIt)
Generally use of this should be shunned, except to use a FORTRAN routine or something similar.
size_t size() const
Definition IPosition.h:570
StorageInitPolicy
Definition ArrayBase.h:49
@ COPY
COPY is used when an internal copy of the storage is to be made.
Definition ArrayBase.h:52
struct Node * first
Definition malloc.h:328
this file contains all the compiler specific defines
Definition mainpage.dox:28
LatticeExprNode pa(const LatticeExprNode &left, const LatticeExprNode &right)
This function finds 180/pi*atan2(left,right)/2.
LatticeExprNode mask(const LatticeExprNode &expr)
This function returns the mask of the given expression.
void swap(Array< T > &first, Array< T > &second)
Swap the first array with the second.
Definition Array.h:987
LatticeExprNode value(const LatticeExprNode &expr)
This function returns the value of the expression without a mask.
TableExprNode marray(const TableExprNode &array, const TableExprNode &mask)
Form a masked array.
Definition ExprNode.h:1939
Define real & complex conjugation for non-complex types and put comparisons into std namespace.
Definition Complex.h:350
This is a tag for the constructor that may be used to construct an uninitialized Array.
Definition Array.h:179