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>
155class Array : public ArrayBase {
156 public:
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>,
167 // elements are initialized. This inconsistent behavior confuses programmers and make it hard to
168 // write efficient and generic code using template. Especially when <src>T</src> is of type
169 // <src>Complex</src> or <src>DComplex</src> and it is unnecessary to initialize, provide
170 // initPolicy with value <src>NO_INIT</src> to skip the initialization. Therefore, it is strongly
171 // recommended to explicitly provide initPolicy parameter,
172 explicit Array(const IPosition& shape);
173
174 // Create an array of the given shape and initialize it with the
175 // initial value.
176 // Storage is allocated by <src>DefaultAllocator<T></src>.
177 Array(const IPosition& shape, const T& initialValue);
178
179 // This is a tag for the constructor that may be used to construct an uninitialized Array.
182
183 // Constructor to create an uninitialized array. This constructor can for example
184 // be called with:
185 // <srcblock>
186 // Array<int> a(shape, Array<int>::uninitialized);
187 // </srcblock>
188 Array(const IPosition& shape, uninitializedType);
189
190 // Construct a one-dimensional array from an initializer list.
191 // Example:
192 // <srcblock>
193 // Array<int> a({5, 6, 7, 8});
194 // </srcblock>
195 Array(std::initializer_list<T> list);
196
197 // After construction, this and other reference the same storage.
198 Array(const Array<T>& other);
199
200 // Source will be empty after this call.
201 Array(Array<T>&& source) noexcept;
202
203 // Create an Array of a given shape from a pointer.
204 // If <src>policy</src> is <src>COPY</src>, storage of a new copy is allocated by
205 // <src>DefaultAllocator<T></src>. If <src>policy</src> is <src>TAKE_OVER</src>,
206 // <src>storage</src> will be destructed and released by the specified allocator. <srcblock>
207 // FILE *fp = ...;
208 // typedef DefaultAllocator<int> Alloc;
209 // Alloc::type alloc;
210 // IPosition shape(1, 10);
211 // int *ptr = alloc.allocate(shape.product());
212 // size_t nread = fread(ptr, sizeof(int), shape.product(), fp);
213 // Array<int> ai(shape, ptr, TAKE_OVER);
214 // </srcblock>
216
217 // Create an Array of a given shape from a pointer. Because the pointer
218 // is const, a copy is always made.
219 // The copy is allocated by <src>DefaultAllocator<T></src>.
220 Array(const IPosition& shape, const T* storage);
221
222 // Construct an array from an iterator and a shape.
223 template <typename InputIterator>
224 Array(const IPosition& shape, InputIterator startIter);
225
226 // Frees up storage only if this array was the last reference to it.
227 virtual ~Array() noexcept;
228
229 // Make an empty array of the same template type.
230 virtual std::unique_ptr<ArrayBase> makeArray() const override;
231
232 // Assign the other array to this array.
233 // If the shapes mismatch, this array is resized.
234 // <group>
235 void assign(const Array<T>& other);
236
237 void assignBase(const ArrayBase& other, bool checkType = true) override;
238 // </group>
239
240 // Set every element of the array to "value." Also could use the
241 // assignment operator which assigns an array from a scalar.
242 void set(const T& value);
243
244 // Apply the function to every element of the array. This modifies
245 // the array in place.
246 // (TODO this version made the other versions of apply() redundant)
247 template <typename Callable>
248 void apply(Callable function);
249
250 // After invocation, this array and other reference the same storage. That
251 // is, modifying an element through one will show up in the other. The
252 // arrays appear to be identical; they have the same shape.
253 // <br>Please note that this function makes it possible to reference a
254 // const Array, thus effectively it makes a const Array non-const.
255 // Although this may seem undesirable at first sight, it is necessary to
256 // be able to make references to temporary Array objects, in particular to
257 // Array slices. Otherwise one first needs to use the copy constructor.
258 // # The const has been introduced on 2005-Mar-31 because of the hassle
259 // # involved in calling the copy ctor before reference.
260 virtual void reference(const Array<T>& other);
261
262 // Copy the values in other to this. If the array on the left hand
263 // side has no elements, then it is resized to be the same size as
264 // as the array on the right hand side. Otherwise, the arrays must
265 // conform (same shapes).
266 // <srcblock>
267 // IPosition shape(2,10,10); // some shape
268 // Array<double> ad(shape);
269 // //...
270 // Array<double> ad2; // N.B. ad2.nelements() == 0
271 // ad2 = ad; // ad2 resizes, then elements
272 // // are copied.
273 // shape = 20;
274 // Array<double> ad3(shape);
275 // ad3 = ad; // Error: arrays do not conform
276 // </srcblock>
277 // Note that the assign function can be used to assign a
278 // non-conforming array.
279 Array<T>& assign_conforming(const Array<T>& other) {
280 return assign_conforming_implementation(other, std::is_copy_assignable<T>());
281 }
282
283 // Copy to this those values in marray whose corresponding elements
284 // in marray's mask are true.
285 // <thrown>
286 // <li> ArrayConformanceError
287 // </thrown>
288 //
290
291 // TODO we should change the semantics
292 Array<T>& operator=(const Array<T>& other) { return assign_conforming(other); }
293
294 // Calls assign_conforming().
296
297 // The move operator takes the storage from the given array. After moving an
298 // Array, the source Array will be left empty.
300
301 // Set every element of this array to "value". In other words, a scalar
302 // behaves as if it were a constant conformant array.
304
305 // This makes a copy of the array and returns it. This can be
306 // useful for, e.g. making working copies of function arguments
307 // that you can write into.
308 // <srcblock>
309 // void someFunction(const Array<int> &arg)
310 // {
311 // Array<int> tmp(arg.copy());
312 // // ...
313 // }
314 // </srcblock>
315 // Note that since the copy constructor makes a reference, if we just
316 // created used to copy constructor, modifying "tmp" would also
317 // modify "arg". Clearly another alternative would simply be:
318 // <srcblock>
319 // void someFunction(const Array<int> &arg)
320 // {
321 // Array<int> tmp;
322 // tmp = arg;
323 // // ...
324 // }
325 // </srcblock>
326 // which likely would be simpler to understand. (Should copy()
327 // be deprecated and removed?)
328 //
329 // TODO deprecate
330 Array<T> copy() const;
331
332 // This function copies the matching part of from array to this array.
333 // The matching part is the part with the minimum size for each axis.
334 // E.g. if this array has shape [4,5,6] and from array has shape [7,3],
335 // the matching part has shape [4,3].
336 // <br>Note it is used by the resize function if
337 // <src>copyValues==true</src>.
338 void copyMatchingPart(const Array<T>& from);
339
340 // This ensures that this array does not reference any other storage.
341 // <note role=tip>
342 // When a section is taken of an array with non-unity strides,
343 // storage can be wasted if the array, which originally contained
344 // all the data, goes away. unique() also reclaims storage. This
345 // is an optimization users don't normally need to understand.
346 //
347 // <srcblock>
348 // IPosition shape(...), blc(...), trc(...), inc(...);
349 // Array<float> af(shape);
350 // inc = 2; // or anything > 1
351 // Array<float> aSection.reference(af(blc, trc, inc));
352 // af.reference(anotherArray);
353 // // aSection now references storage that has a stride
354 // // in it, but nothing else is. Storage is wasted.
355 // aSection.unique();
356 // </srcblock>
357 // </note>
358 void unique();
359
360 // Create an STL vector from an Array. The created vector is a linear
361 // representation of the Array memory. See
362 // <linkto class=Vector>Vector</linkto> for
363 // details of the operation and its reverse (i.e. creating a
364 // <src>Vector</src> from a <src>vector</src>), and for details of
365 // definition and instantiation.
366 // <group>
367 template <class U>
368 void tovector(std::vector<T, U>& out) const;
369 std::vector<T> tovector() const;
370 // </group>
371
372 // It is occasionally useful to have an array which access the same
373 // storage appear to have a different shape. For example,
374 // turning an N-dimensional array into a Vector.
375 // <br>When the array data are contiguous, the array can be reshaped
376 // to any form as long as the number of elements stays the same.
377 // When not contiguous, it is only possible to remove or add axes
378 // with length 1.
379 // <srcblock>
380 // IPosition squareShape(2,5,5);
381 // Array<float> square(squareShape);
382 // IPosition lineShape(1,25);
383 // Vector<float> line(square.reform(lineShape));
384 // // "square"'s storage may now be accessed through Vector "line"
385 // </srcblock>
387
388 // Having an array that can be reused without requiring reallocation can
389 // be useful for large arrays. The method reformOrResize permits this
390 // usage.
391 //
392 // The reformOrResize method first attempts to reform the matrix so that
393 // it reuses the existing storage for an array with a new shape. If the
394 // existing storage will not hold the new shape, then the method will
395 // resize the array when resizeIfNeeded is true; if a resize is needed and
396 // resizeIfNeeded is false, then an ArrayConformanceError is thrown. The
397 // copyDataIfNeeded parameter is passed to resize if resizing is performed.
398 // resizePercentage is the percent of additional storage to be addeed when
399 // a resize is performed; this allows the allocations to be amortized when
400 // the caller expects to be calling this method again in the future. The
401 // parameter is used to define an allocation shape which is larger than
402 // the newShape by increasing the last dimension by resizePercentage percent
403 // (i.e., lastDim = (lastDim * (100 + resizePercentage)) / 100). If
404 // resizePercentage <= 0 then resizing uses newShape as-is. Returns true
405 // if resizing (allocation) was performed.
406 //
407 // To truncate the array so that it no longer holds additional storage,
408 // use the resize method.
409 //
410 // Array may not be shared with another Array object during this call.
411 // Exception thrown if it is shared.
412
413 bool reformOrResize(const IPosition& newShape, size_t resizePercentage = 0,
414 bool resizeIfNeeded = true);
415
416 // Use this method to extend or reduce the last dimension of an array. If
417 // sufficient excess capacity exists then the bookkeeping is adjusted to
418 // support the new shape. If insufficient storage exists then a new array
419 // is allocated (unless resizeIfNeeded is false; then an exception is thrown).
420 // If resizing is not required then the data remains untouched; if resizing
421 // is required then the data is copied into the new storage. The resizePercentage
422 // works the same as for reformOrResize (see above). This method never releases
423 // extra storage; use "resize" to do this. Array may not be sharing storage
424 // with another array at call time; an exception will be thrown if the array is shared.
425 // Returns true if the array was extension required a Array<T>::resize operation.
426
427 bool adjustLastAxis(const IPosition& newShape, size_t resizePercentage = 0,
428 bool resizeIfNeeded = true);
429
430 // Returns the number of elements allocated. This value is >= to the value returned
431 // by size().
432
433 size_t capacity() const;
434
435 // These member functions remove degenerate (ie. length==1) axes from
436 // Arrays. Only axes greater than startingAxis are considered (normally
437 // one wants to remove trailing axes). The first two of these functions
438 // return an Array reference with axes removed. The latter two functions
439 // let this Array object reference the 'other' array with degenerated axes
440 // removed.
441 // <br>
442 // Unless throwIfError is false, an exception will be thrown if
443 // startingAxis exceeds the array's dimensionality.
444 // <br>
445 // The functions with argument <src>ignoreAxes</src> do
446 // not consider the axes given in that argument. In this way it can be
447 // achieved that degenerate axes are kept.
448 // <note role=caution> When the two functions returning <src>void</src>
449 // are invoked on a derived object (e.g. Matrix), an exception is
450 // thrown if removing the degenerate axes from other does not result
451 // in a correct number of axes.
452 // </note>
453 // <group>
454 Array<T> nonDegenerate(size_t startingAxis = 0, bool throwIfError = true) const;
455 Array<T> nonDegenerate(const IPosition& ignoreAxes) const;
456 void nonDegenerate(const Array<T>& other, size_t startingAxis = 0, bool throwIfError = true);
457 void nonDegenerate(const Array<T>& other, const IPosition& ignoreAxes) {
458 doNonDegenerate(other, ignoreAxes);
459 }
460 // </group>
461
462 // Remove degenerate axes from this Array object.
463 // Note it does not make sense to use these functions on a derived object
464 // like Matrix, because it is not possible to remove axes from them.
465 // <group>
466 void removeDegenerate(size_t startingAxis = 0, bool throwIfError = true);
467 void removeDegenerate(const IPosition& ignoreAxes);
468 // </group>
469
470 // This member function returns an Array reference with the specified
471 // number of extra axes, all of length one, appended to the end of the
472 // Array. Note that the <src>reform</src> function can also be
473 // used to add extra axes.
474 // <group>
475 const Array<T> addDegenerate(size_t numAxes) const;
476 Array<T> addDegenerate(size_t numAxes);
477 // </group>
478
479 // Make this array a different shape. If <src>copyValues==true</src>
480 // the old values are copied over to the new array.
481 // Copying is done on a per axis basis, thus a subsection with the
482 // minimum of the old and new shape is copied.
483 // <br>Resize without argument is equal to resize(IPosition()).
484 // <br>It is important to note that if multiple Array objects
485 // reference the same data storage, this Array object still references
486 // the same data storage as the other Array objects if the shape does
487 // not change. Otherwise this Array object references newly allocated
488 // storage, while the other Array objects still reference the existing
489 // data storage.
490 // <br>If you want to be sure that the data storage of this Array object
491 // is not referenced by other Array objects, the function unique should
492 // be called first.
493 // <group>
494 void resize();
495
496 void resize(const IPosition& newShape, bool copyValues = false) override;
497 // </group>
498
499 // Access a single element of the array. This is relatively
500 // expensive. Extensive indexing should be done through one
501 // of the Array specializations (Vector, Matrix, Cube).
502 // <group>
504 const T& operator()(const IPosition&) const;
505 // </group>
506
507 // Get a reference to an array section extending
508 // from start to end (inclusive).
509 // <group>
511 const Array<T> operator()(const IPosition& start, const IPosition& end) const;
512 // Along the ith axis, every inc[i]'th element is chosen.
513 Array<T> operator()(const IPosition& start, const IPosition& end, const IPosition& inc);
514 const Array<T> operator()(const IPosition& start, const IPosition& end,
515 const IPosition& inc) const;
516 // </group>
517
518 // Get a reference to an array section using a Slicer.
519 // <group>
521 const Array<T> operator()(const Slicer&) const;
522 // </group>
523
524 // Get a reference to a section of an array.
525 // This is the same as operator(), but can be used in a type-agnostic way.
526 std::unique_ptr<ArrayBase> getSection(const Slicer&) const override;
527
528 // Get the subset given by the i-th value of the last axis. So for a cube
529 // it returns the i-th xy plane. For a Matrix it returns the i-th row.
530 // The returned array references the original array data; its dimensionality
531 // is one less. For a 1-dim array it still returns a 1-dim array.
532 // <note>This function should not be used in tight loops as it is (much)
533 // slower than iterating using begin() and end(), ArrayIter, or
534 // ArrayAccessor.</note>
535 Array<T> operator[](size_t i) const;
536
537 // Get the diagonal of each matrix part in the full array.
538 // The matrices are taken using axes firstAxes and firstAxis+1.
539 // diag==0 is main diagonal; diag>0 above the main diagonal; diag<0 below.
540 Array<T> diagonals(size_t firstAxis = 0, long long diag = 0) const;
541
542 // The array is masked by the input LogicalArray.
543 // This mask must conform to the array.
544 // <group>
547 // </group>
548
549 // The array is masked by the input MaskedLogicalArray.
550 // The mask is effectively the AND of the internal LogicalArray
551 // and the internal mask of the MaskedLogicalArray.
552 // The MaskedLogicalArray must conform to the array.
553 // <group>
556 // </group>
557
558 // The number of references the underlying storage has assigned to it.
559 // It is 1 unless there are outstanding references to the storage (e.g.,
560 // through a slice). Normally you have no need to do this since the
561 // arrays handle all of the references for you.
562 // NB: Even when nrefs()==1, the array might be shared, because the
563 // the storage itself might be shared. Therefore, this function should
564 // not be used outside debugging.
565 // TODO make protected.
566 size_t nrefs() const;
567
568 // Check to see if the Array is consistent. This is about the same thing
569 // as checking for invariants. If AIPS_DEBUG is defined, this is invoked
570 // after construction and on entry to most member functions.
571 virtual bool ok() const override;
572
573 // Are the shapes identical?
574 // <group>
575 bool conform(const Array<T>& other) const { return conform2(other); }
576 bool conform(const MaskedArray<T>& other) const;
577 // </group>
578
579 // Get a pointer to the beginning of the array.
580 // Note that the array may not be contiguous.
581 // <group>
582 T* data() { return begin_p; }
583 const T* data() const { return begin_p; }
584 // </group>
585
586 // Generally use of this should be shunned, except to use a FORTRAN routine
587 // or something similar. Because you can't know the state of the underlying
588 // data layout (in particular, if there are increments) sometimes the
589 // pointer returned will be to a copy, but often this won't be necessary.
590 // A boolean is returned which tells you if this is a copy (and hence the
591 // storage must be deleted). Note that if you don't do anything unusual,
592 // getStorage followed by freeStorage or putStorage will do the deletion
593 // for you (if required). e.g.:
594 // <srcblock>
595 // Array<int> a(shape); ...
596 // bool deleteIt; int *storage = a.getStorage(deleteIt);
597 // foo(storage, a.nelements()); a.puStorage(storage, deleteIt);
598 // // or a.freeStorage(storage, deleteIt) if a is const.
599 // </srcblock>
600 // NB: However, if you only use getStorage, you will have to delete the
601 // pointer yourself using freeStorage().
602 //
603 // It would probably be useful to have corresponding "copyin" "copyout"
604 // functions that used a user supplied buffer.
605 // Note that deleteIt is set in this function.
606 // <group>
607 T* getStorage(bool& deleteIt);
608 const T* getStorage(bool& deleteIt) const {
609 // The cast is OK because the return pointer will be cast to const
610 return const_cast<Array<T>*>(this)->getStorage(deleteIt);
611 }
612 void* getVStorage(bool& deleteIt) override;
613 const void* getVStorage(bool& deleteIt) const override;
614 // </group>
615
616 // putStorage() is normally called after a call to getStorage() (cf).
617 // The "storage" pointer is set to zero.
618 void putStorage(T*& storage, bool deleteAndCopy);
619 void putVStorage(void*& storage, bool deleteAndCopy) override;
620
621 // If deleteIt is set, delete "storage". Normally freeStorage calls
622 // will follow calls to getStorage. The reason the pointer is "const"
623 // is because only const pointers are released from const arrays.
624 // The "storage" pointer is set to zero.
625 // TODO this function can not be const for stateful allocators
626 void freeStorage(const T*& storage, bool deleteIt) const;
627 void freeVStorage(const void*& storage, bool deleteIt) const override;
628
629 // Replace the data values with those in the pointer <src>storage</src>.
630 // The results are undefined if storage does not point at nelements() or
631 // more data elements. After takeStorage() is called, <src>nrefs()</src>
632 // is 1.
633 // <group>
634 // If <src>policy</src> is <src>COPY</src>, storage of a new copy is allocated by
635 // <src>allocator</src>. If <src>policy</src> is <src>TAKE_OVER</src>, <src>storage</src> will be
636 // destructed and released by <src>allocator</src>.
637 virtual void takeStorage(const IPosition& shape, T* storage, StorageInitPolicy policy = COPY);
638
639 // Since the pointer is const, a copy is always taken.
640 // Storage of a new copy is allocated by the specified allocator.
641 virtual void takeStorage(const IPosition& shape, const T* storage);
642 // </group>
643
644 // Used to iterate through Arrays. Derived classes VectorIterator and
645 // MatrixIterator are probably more useful.
646 friend class ArrayIterator<T>;
647
648 // Create an ArrayIterator object of the correct type.
649 std::unique_ptr<ArrayPositionIterator> makeIterator(size_t byDim) const override;
650
651 // <group name=STL-iterator>
652 // See the function begin() and end() for a detailed description
653 // of the STL iterator capability.
654 class BaseIteratorSTL {
655 public:
656 // Create the begin const_iterator object for an Array.
657 explicit BaseIteratorSTL(const Array<T>&);
658 // Create the end const_iterator object for an Array.
659 // It also acts as the default constructor.
660 explicit BaseIteratorSTL(const T* end = 0)
662 itsLineEnd(0),
663 itsLineIncr(0),
664 itsLineAxis(0),
665 itsArray(0),
666 itsContig(false) {}
667
668 void nextElem() {
669 itsPos++;
670 if (!itsContig) {
672 if (itsPos > itsLineEnd) increment();
673 }
674 }
675 void nextLine() {
677 increment();
678 }
679
680 bool operator==(const BaseIteratorSTL& other) const { return itsPos == other.itsPos; }
681
682 bool operator!=(const BaseIteratorSTL& other) const { return itsPos != other.itsPos; }
683
684 T* getPos() { return const_cast<T*>(itsPos); }
685
686 friend std::ostream& operator<<(std::ostream& os, const BaseIteratorSTL& iter) {
687 os << iter.itsPos;
688 return os;
689 }
690
691 protected:
692 // Increment iterator for a non-contiguous array.
693 void increment();
694
695 const T* itsPos;
696 const T* itsLineEnd;
703 };
704
706 public:
707 // <group name=STL-iterator-typedefs>
708 typedef T value_type;
711 typedef std::size_t size_type;
712 typedef ptrdiff_t difference_type;
713 typedef std::forward_iterator_tag iterator_category;
714 // </group>
715
716 // Create the begin iterator object for an Array.
717 explicit IteratorSTL(Array<T>& arr) : BaseIteratorSTL(arr) {}
718 // Create the end iterator object for an Array.
719 // It also acts as the default constructor.
720 explicit IteratorSTL(const T* end = 0) : BaseIteratorSTL(end) {}
721
723 this->nextElem();
724 return *this;
725 }
727 IteratorSTL old(*this);
728 this->nextElem();
729 return old;
730 }
731
732 T& operator*() { return *this->getPos(); }
733 T* operator->() { return this->getPos(); }
734 };
735
737 public:
738 // <group name=STL-const-iterator-typedefs>
739 typedef T value_type;
740 typedef const value_type* pointer;
741 typedef const value_type& reference;
742 typedef std::size_t size_type;
743 typedef ptrdiff_t difference_type;
744 typedef std::forward_iterator_tag iterator_category;
745 // </group>
746
747 // Create the begin const_iterator object for an Array.
748 explicit ConstIteratorSTL(const Array<T>& arr) : BaseIteratorSTL(arr) {}
749 // Create the end const_iterator object for an Array.
750 // It also acts as the default constructor.
751 explicit ConstIteratorSTL(const T* end = 0) : BaseIteratorSTL(end) {}
752 // Create from a non-const iterator.
754
756 this->nextElem();
757 return *this;
758 }
760 ConstIteratorSTL old(*this);
761 this->nextElem();
762 return old;
763 }
764
765 const T& operator*() const { return *this->itsPos; }
766 const T* operator->() { return this->itsPos; }
767
768 const T* pos() const { return this->itsPos; }
769 };
770 // </group>
771
772 // Define the STL-style iterator functions (only forward iterator).
773 // It makes it possible to iterate through all data elements of an array
774 // and to use it common STL functions.
775 // The end() function is relatively expensive, so it should not be
776 // used inside a for statement. It is much better to call it beforehand
777 // as shown in the example below. Furthermore it is very important to
778 // use <src>++iter</src>, because <src>iter++</src> is 4 times slower.
779 // <srcblock>
780 // Array<int> arr(shape);
781 // Array<int>::iterator iterend(arr.end());
782 // for (Array<int>::iterator iter=arr.begin(); iter!=iterend; ++iter) {
783 // *iter += 1;
784 // }
785 // </srcblock>
786 // The Array class supports random access, so in principle a random
787 // iterator could be implemented, but its performance would not be great,
788 // especially for non-contiguous arrays.
789 // <br>Some other STL like functions exist for performance reasons.
790 // If the array is contiguous, it is possible to use the
791 // <src>cbegin</src> and <src>cend</src> functions which are
792 // about 10% faster.
793 // <group name=iterator-typedefs>
794 // STL-style typedefs.
795 // <group>
796
797 // Element type
798 typedef T value_type;
799 // TODO This is how std containers define a reference type, but
800 // the name 'reference' is already taken by a method.
801 // typedef T& reference;
802 typedef const T& const_reference;
803 // Pointer to an element type
804 typedef T* pointer;
805 // Constant pointer to the element type
806 typedef const T* const_pointer;
809 typedef T* contiter;
810 typedef const T* const_contiter;
811 // </group>
812 // Get the begin iterator object for any array.
813 // <group>
814 iterator begin() { return iterator(*this); }
815 const_iterator begin() const { return const_iterator(*this); }
816 iterator end() { return iterator(end_p); }
818 // </group>
819
820 // Get the begin iterator object for a contiguous array.
821 // <group>
822 contiter cbegin() { return begin_p; }
823 const_contiter cbegin() const { return begin_p; }
824 contiter cend() { return end_p; }
825 const_contiter cend() const { return end_p; }
826 // </group>
827
828 // </group>
829
830 private:
831 // Implementation of constructor taking a Shape, a Templated parameter and an allocator.
832 // This method implements it for when T is integral, in which case the templated parameter
833 // is the initial value.
834 template <typename Integral>
835 Array(const IPosition& shape, Integral startIter, std::true_type /*is_integral*/);
836
837 // Implementation of constructor taking a Shape, a Templated parameter and an allocator.
838 // This method implements it for when T is NOT integral, in which case the templated parameter
839 // is an iterator.
840 template <typename InputIterator>
841 Array(const IPosition& shape, InputIterator startIter, std::false_type /*is_integral*/);
842
843 // Implementation for assign for copyable types
844 Array<T>& assign_conforming_implementation(const Array<T>& other, std::true_type);
845 // Implementation for assign for non-copyable types: can not be assigned
847 throw ArrayError("Can not assign from non-copyable object");
848 }
849 static void copyToContiguousStorage(T* dst, Array<T> const& src, std::true_type);
850 static void copyToContiguousStorage(T*, Array<T> const&, std::false_type) {
851 throw ArrayError("Can not coy from non-copyable object");
852 }
853
854 // An Array is unique when the container is shared and when nrefs==1.
855 bool isUnique() const { return !data_p->is_shared() && nrefs() == 1; }
856
857 protected:
858 // Source will be empty with given shape after this call.
859 Array(Array<T>&& source, const IPosition& shapeForSource) noexcept;
860
861 template <typename ST>
862 friend void swap(Array<ST>& left, Array<ST>& right);
863
864 // Swap this array with another array.
865 // Normally, casacore::swap() should be used instead.
866 void swap(Array<T>& other);
867
868 // pre/post processing hook of takeStorage() for subclasses.
869 virtual void preTakeStorage(const IPosition&) {}
870
871 virtual void postTakeStorage() {}
872
873 // This function is called when this array is about to be resized, before
874 // any work is done. Subclasses can throw an exception if the size doesn't
875 // match, e.g. if a Matrix is resized to have 3 dimensions.
876 // Before this function existed, assign-like functions had to be virtual.
877 // However, for non-copyable types, assign can't exist. This is fine for
878 // non-virtual methods (they just can't be called), but virtual methods
879 // cause the who class to fail to be instantiatable.
880 void checkBeforeResize(const IPosition& newShape) {
881 if (fixedDimensionality() != 0 && newShape.size() != fixedDimensionality())
882 throw(ArrayNDimError(fixedDimensionality(), newShape.size(),
883 std::string("Invalid size given to ") + typeid(*this).name() +
884 ": should have dimensionality of " +
885 std::to_string(fixedDimensionality())));
886 }
887
888 // Subclasses can return their dimensionality. The Array class will make sure
889 // that whenever it is resized, the dimensionality is checked.
890 // Array's constructors do not check the dimensionality, because the subclass
891 // hasn't been created yet at that point. Subclasses should therefore make
892 // sure to call the constructors appropriately.
893 // For classes that return 0, any resize will be allowed.
894 virtual size_t fixedDimensionality() const { return 0; }
895
896 virtual void checkAssignableType(ArrayBase& arrayBase) const {
897 const Array<T>* pa = dynamic_cast<const Array<T>*>(&arrayBase);
898 if (pa == nullptr) {
899 throw ArrayError("ArrayBase& has incorrect template type");
900 }
901 }
902
903 static void copyToContiguousStorage(T* dst, Array<T> const& src) {
904 copyToContiguousStorage(dst, src, std::is_copy_assignable<T>());
905 }
906
907 // Remove the degenerate axes from the Array object.
908 // This is the implementation of the nonDegenerate functions.
909 // It has a different name to be able to make it virtual without having
910 // the "hide virtual function" message when compiling derived classes.
911 virtual void doNonDegenerate(const Array<T>& other, const IPosition& ignoreAxes);
912
913 // Shared pointer to a Storage that contains the data.
914 std::shared_ptr<arrays_internal::Storage<T>> data_p;
915
916 // This pointer is adjusted to point to the first element of the array.
917 // It is not necessarily the same thing as data->storage() since
918 // this array might be a section, e.g. have a blc which shifts us forward
919 // into the block.
921
922 // The end for an STL-style iteration.
924
925 // Fill the steps and the end for a derived class.
926 void makeSteps() {
928 this->setEndIter();
929 }
930
931 // Set the end iterator.
932 void setEndIter() {
933 end_p = (nels_p == 0
934 ? 0
936 : begin_p + size_t(length_p(ndim() - 1)) * steps_p(ndim() - 1)));
937 }
938};
939
940// Swap the first array with the second.
941// This is more efficient than std::swap()
942template <typename T>
943void swap(Array<T>& first, Array<T>& second) {
944 first.swap(second);
945}
946
947// # Declare extern templates for often used types.
948extern template class Array<bool>;
949extern template class Array<char>;
950extern template class Array<unsigned char>;
951extern template class Array<short>;
952extern template class Array<unsigned short>;
953extern template class Array<int>;
954extern template class Array<long long>;
955extern template class Array<float>;
956extern template class Array<double>;
957
958} // namespace casacore
959
960#include "ArrayStr.h"
961#include "Array.tcc"
962
963#endif
size_t ndim() const
The dimensionality of this array.
Definition ArrayBase.h:94
size_t nels_p
Number of elements in the array.
Definition ArrayBase.h:249
ArrayBase() noexcept
bool contiguous_p
Are the data contiguous?
Definition ArrayBase.h:253
void baseMakeSteps()
Make the indexing step sizes.
const IPosition & shape() const
The length of each axis.
Definition ArrayBase.h:116
IPosition length_p
Used to hold the shape, increment into the underlying storage and originalLength of the array.
Definition ArrayBase.h:256
IPosition steps_p
Used to hold the step to next element in each dimension.
Definition ArrayBase.h:258
bool conform2(const ArrayBase &other) const
Are the shapes identical?
Definition ArrayBase.h:228
Thrown when two arrays have different dimensionality.
Definition ArrayError.h:127
bool operator==(const BaseIteratorSTL &other) const
Definition Array.h:680
const Array< T > * itsArray
Definition Array.h:701
BaseIteratorSTL(const T *end=0)
Create the end const_iterator object for an Array.
Definition Array.h:661
void increment()
Increment iterator for a non-contiguous array.
bool operator!=(const BaseIteratorSTL &other) const
Definition Array.h:682
friend std::ostream & operator<<(std::ostream &os, const BaseIteratorSTL &iter)
Definition Array.h:686
BaseIteratorSTL(const Array< T > &)
Create the begin const_iterator object for an Array.
std::forward_iterator_tag iterator_category
Definition Array.h:745
const value_type * pointer
Definition Array.h:741
ConstIteratorSTL operator++(int)
Definition Array.h:759
const ConstIteratorSTL & operator++()
Definition Array.h:755
ConstIteratorSTL(const Array< T > &arr)
Create the begin const_iterator object for an Array.
Definition Array.h:748
const value_type & reference
Definition Array.h:742
ConstIteratorSTL(const IteratorSTL &iter)
Create from a non-const iterator.
Definition Array.h:753
ConstIteratorSTL(const T *end=0)
Create the end const_iterator object for an Array.
Definition Array.h:751
const T & operator*() const
Definition Array.h:765
const IteratorSTL & operator++()
Definition Array.h:722
IteratorSTL operator++(int)
Definition Array.h:726
IteratorSTL(Array< T > &arr)
Create the begin iterator object for an Array.
Definition Array.h:717
std::forward_iterator_tag iterator_category
Definition Array.h:714
IteratorSTL(const T *end=0)
Create the end iterator object for an Array.
Definition Array.h:720
IteratorSTL iterator
Definition Array.h:807
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:850
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:869
void assign(const Array< LogicalArrayElem > &other)
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:582
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< LogicalArrayElem > > data_p
Definition Array.h:914
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:292
Array(const IPosition &shape, InputIterator startIter, std::false_type)
Implementation of constructor taking a Shape, a Templated parameter and an allocator.
LogicalArrayElem * begin_p
Definition Array.h:920
const Array< T > operator()(const IPosition &start, const IPosition &end) const
iterator begin()
Get the begin iterator object for any array.
Definition Array.h:814
const T * const_contiter
Definition Array.h:810
contiter cend()
Definition Array.h:824
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:808
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:822
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:802
virtual void postTakeStorage()
Definition Array.h:871
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:855
void makeSteps()
Fill the steps and the end for a derived class.
Definition Array.h:926
const T * const_pointer
Constant pointer to the element type.
Definition Array.h:806
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:903
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:880
const T * data() const
Definition Array.h:583
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:846
void nonDegenerate(const Array< T > &other, const IPosition &ignoreAxes)
Definition Array.h:457
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
const_iterator begin() const
Definition Array.h:815
const_contiter cbegin() const
Definition Array.h:823
Array< LogicalArrayElem > & assign_conforming(const Array< LogicalArrayElem > &other)
Definition Array.h:279
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:817
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.
const MaskedArray< T > operator()(const MaskedLogicalArray &mask) const
The array is masked by the input MaskedLogicalArray.
void setEndIter()
Set the end iterator.
Definition Array.h:932
Array(Array< T > &&source) noexcept
Source will be empty after this call.
T * pointer
Pointer to an element type.
Definition Array.h:804
virtual size_t fixedDimensionality() const
Subclasses can return their dimensionality.
Definition Array.h:894
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:575
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:825
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
const MaskedArray< T > operator()(const LogicalArray &mask) const
The array is masked by the input LogicalArray.
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.
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:896
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 LogicalArrayElem &value)
virtual void reference(const Array< LogicalArrayElem > &other)
MaskedArray< T > operator()(const LogicalArray &mask)
std::unique_ptr< ArrayBase > getSection(const Slicer &) const override
Get a reference to a section of an array.
void apply(Callable function)
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.
const T * getStorage(bool &deleteIt) const
Definition Array.h:608
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:798
void assignBase(const ArrayBase &other, bool checkType=true) override
static void copyToContiguousStorage(T *dst, Array< T > const &src, std::true_type)
MaskedArray< T > operator()(const MaskedLogicalArray &mask)
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:552
StorageInitPolicy
Definition ArrayBase.h:48
@ COPY
COPY is used when an internal copy of the storage is to be made.
Definition ArrayBase.h:51
struct Node * first
Definition malloc.h:325
For temporary backward namespace compatibility, use casa as alias for casacore.
Definition mainpage.dox:28
LatticeExprNode pa(const LatticeExprNode &left, const LatticeExprNode &right)
This function finds 180/pi*atan2(left,right)/2.
T * storage()
If you really, really, need a "raw" pointer to the beginning of the storage area this will give it to...
Definition Block.h:559
LatticeExprNode mask(const LatticeExprNode &expr)
This function returns the mask of the given expression.
Array< LogicalArrayElem > LogicalArray
Definition ArrayFwd.h:17
MaskedArray< LogicalArrayElem > MaskedLogicalArray
Definition ArrayFwd.h:20
void swap(Array< T > &first, Array< T > &second)
Swap the first array with the second.
Definition Array.h:943
TableExprNode marray(const TableExprNode &array, const TableExprNode &mask)
Form a masked array.
Definition ExprNode.h:1567
NewDelAllocator< T > NewDelAllocator< T >::value
Definition Allocator.h:360
Define real & complex conjugation for non-complex types and put comparisons into std namespace.
Definition Complex.h:344
This is a tag for the constructor that may be used to construct an uninitialized Array.
Definition Array.h:180