//# Vector.h: A 1-D Specialization of the Array Class //# Copyright (C) 1993,1994,1995,1996,1998,1999,2000,2001,2002,2003 //# Associated Universities, Inc. Washington DC, USA. //# //# This library is free software; you can redistribute it and/or modify it //# under the terms of the GNU Library General Public License as published by //# the Free Software Foundation; either version 2 of the License, or (at your //# option) any later version. //# //# This library is distributed in the hope that it will be useful, but WITHOUT //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public //# License for more details. //# //# You should have received a copy of the GNU Library General Public License //# along with this library; if not, write to the Free Software Foundation, //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. //# //# Correspondence concerning AIPS++ should be addressed as follows: //# Internet email: aips2-request@nrao.edu. //# Postal address: AIPS++ Project Office //# National Radio Astronomy Observatory //# 520 Edgemont Road //# Charlottesville, VA 22903-2475 USA //# //# $Id$ #ifndef CASA_VECTOR_2_H #define CASA_VECTOR_2_H //# Includes #include "Array.h" namespace casacore { //#Begin namespace casacore // A 1-D Specialization of the Array class // // // // Vector objects are one-dimensional specializations (e.g., more convenient // and efficient indexing) of the general Array class. You might also want // to look at the Array documentation to see inherited functionality. // // Generally the member functions of Array are also available in // Vector versions // which take an integer where the array needs an IPosition. Since the Vector // is one-dimensional, the IPositions are overkill, although you may // use those versions if you want to. // // Vector vi(100); // Vector 100 elements long. // vi.resize(50); // Now only 50 long. // // // Slices may be taken with the Slice class. To take a slice, one "indexes" // with Slice(start, length, inc) where end and inc are optional. // // Vector vf(100); // //... // vf(Slice(0,50,2)) = vf(Slice(1,50,2)); // Copy values from odd onto even // Vector firstHalf, secondHalf; // firstHalf.reference(vf(Slice(0,50))); // secondHalf.reference(vf(Slice(50,50))); // // Now we have aliases for two slices into the Vector // // // Element-by-element arithmetic and logical operations are available (in // aips/ArrayMath.h and aips/ArrayLogical.h) as well as dot and cross // products (in aips/MatrixMath.h). // // A Vector can be constructed from an STL vector. The reverse // operation (Array::tovector()) can construct an STL // vector from any Array. // To create any other STL container from an Array (or // the reverse), always create from/to a vector, and use the // range constructor to create from/to others (like set, list, deque). // // As with the Arrays, if the preprocessor symbol AIPS_DEBUG is // defined at compile time invariants will be checked on entry to most // member functions. Additionally, if AIPS_ARRAY_INDEX_CHECK is defined // index operations will be bounds-checked. Neither of these should // be defined for production code. template class Vector : public Array { public: // A zero-length Vector. Vector(); // A Vector with a defined length and origin of zero. // explicit Vector(size_t Length); explicit Vector(const IPosition& Length); // // A Vector with a defined length and origin of zero. // Fill it with the initial value. // Vector(size_t Length, const T &initialValue); Vector(const IPosition& Length, const T &initialValue); // // An uninitialized Vector with a defined length. // Vector(size_t Length, typename Array::uninitializedType, const Alloc& allocator=Alloc()); Vector(const IPosition& Length, typename Array::uninitializedType, const Alloc& allocator=Alloc()); // // Create a Vector from the given std::vector "other." Make it length "nr" // and copy over that many elements. // This used to take a 'Block' Vector(const std::vector &other, long long nr); // Create a Vector of length other.size() and copy over its values. // This used to take a 'Block' explicit Vector(const std::vector &other, const Alloc& allocator=Alloc()); // Create a Vector from an initializer list. Vector(std::initializer_list list); // Create a reference to other. Vector(const Vector &other); // Move Vector(Vector&& source) noexcept; // Create a reference to the other array. // It is always possible if the array has zero or one axes. // If it has > 1 axes, it is only possible if the array has at most // one axis with length > 1. In that case the degenerated axes are removed. Vector(const Array &other); // Create an Vector of a given shape from a pointer. Vector(const IPosition &shape, T *storage, StorageInitPolicy policy = COPY); // Create an Vector of a given shape from a pointer. Vector(const IPosition &shape, T *storage, StorageInitPolicy policy, Alloc& allocator); // Create an Vector of a given shape from a pointer. Because the pointer // is const, a copy is always made. Vector(const IPosition &shape, const T *storage); template Vector(InputIterator startIter, InputIterator endIter, const Alloc& allocator = Alloc()); // Create a Vector from an STL vector (see tovector() in // Array for the reverse operation). // Both this constructor and the tovector() are // defined in Vector2.cc. // It does implicit promotion/demotion of the type U if different from T. template explicit Vector(const std::vector &other); // Create a Vector from a container iterator and its length. // The length is used instead of last, because the distance // function needed to calculate the length can be expensive. //
A third dummy argument is unfortunately needed to avoid ambiguity // with another Vector constructor (taking two uInts). //
template Vector(Iterator first, size_t size, int dummy); // Resize this Vector to the given length. // The default copyValues flag is false. //# Note that the 3rd resize function is necessary, because that //# function is virtual in the base class (otherwise it would //# be hidden). // Resize without argument is equal to resize(0, false). // using Array::resize; void resize(size_t len, bool copyValues=false) { if (len != this->nelements()) resize(IPosition(1,len), copyValues); } virtual void resize(const IPosition &len, bool copyValues=false) final override; // // Assign to this Vector. If this Vector is zero-length, then resize // to be the same size as other. Otherwise this and other have to be // conformant (same size). //
Note that the assign function can be used to assign a // non-conforming vector. // // TODO unlike Array, a Vector assign to an empty Vector does // not create a reference but does a value copy of the source. // This should be made consistent. using Array::assign_conforming; Vector& assign_conforming(const Vector& source) { return assign_conforming_implementation(source, std::is_copy_assignable()); } Vector& assign_conforming(Vector&& source); // source must be a 1-dimensional array. Vector& assign_conforming(const Array& source); Vector& assign_conforming(Array&& source); // using Array::operator=; Vector& operator=(const Vector& source) { return assign_conforming(source); } Vector& operator=(Vector&& source) { return assign_conforming(std::move(source)); } Vector& operator=(const Array& source) { assign_conforming(source); return *this; } Vector& operator=(Array&& source) { assign_conforming(std::move(source)); return *this; } // Convert a Vector to a Block, resizing the block and copying values. // This is done this way to avoid having the simpler Block class // containing dependencies on the Vector class. //void toBlock(Block &other) const; // Single-pixel addressing. If AIPS_ARRAY_INDEX_CHECK is defined, // bounds checking is performed (not for []).. // T &operator[](size_t index) { return (this->contiguous_p ? this->begin_p[index] : this->begin_p[index*this->inc_p(0)]); } const T &operator[](size_t index) const { return (this->contiguous_p ? this->begin_p[index] : this->begin_p[index*this->inc_p(0)]); } T &operator()(const IPosition &i) { return Array::operator()(i); } const T &operator()(const IPosition &i) const { return Array::operator()(i); } T &operator()(size_t index) { #if defined(AIPS_ARRAY_INDEX_CHECK) this->validateIndex(index); //# Throws an exception on failure #endif return *(this->begin_p + index*this->inc_p(0)); } const T &operator()(size_t index) const { #if defined(AIPS_ARRAY_INDEX_CHECK) this->validateIndex(index); //# Throws an exception on failure #endif return *(this->begin_p + index*this->inc_p(0)); } // // Take a slice of this vector. Slices are always indexed starting // at zero. This uses reference semantics, i.e. changing a value // in the slice changes the original. // // Vector vd(100); // //... // vd(Slice(0,10)) = -1.0; // First 10 elements of vd set to -1 // // Vector operator()(const Slice &slice); const Vector operator()(const Slice &slice) const; // // Slice using IPositions. Required to be defined, otherwise the base // class versions are hidden. // Array operator()(const IPosition &blc, const IPosition &trc, const IPosition &incr) { return Array::operator()(blc,trc,incr); } const Array operator()(const IPosition &blc, const IPosition &trc, const IPosition &incr) const { return Array::operator()(blc,trc,incr); } Array operator()(const IPosition &blc, const IPosition &trc) { return Array::operator()(blc,trc); } const Array operator()(const IPosition &blc, const IPosition &trc) const { return Array::operator()(blc,trc); } Array operator()(const Slicer& slicer) { return Array::operator()(slicer); } const Array operator()(const Slicer& slicer) const { return Array::operator()(slicer); } // // The array is masked by the input LogicalArray. // This mask must conform to the array. // // Return a MaskedArray. MaskedArray operator() (const LogicalArray &mask) const { return Array::operator() (mask); } // Return a MaskedArray. MaskedArray operator() (const LogicalArray &mask) { return Array::operator() (mask); } // // The array is masked by the input MaskedLogicalArray. // The mask is effectively the AND of the internal LogicalArray // and the internal mask of the MaskedLogicalArray. // The MaskedLogicalArray must conform to the array. // // Return a MaskedArray. MaskedArray operator() (const MaskedLogicalArray &mask) const { return Array::operator() (mask); } // Return a MaskedArray. MaskedArray operator() (const MaskedLogicalArray &mask) { return Array::operator() (mask); } // // The length of the Vector. const IPosition &shape() const { return this->length_p; } void shape(int &Shape) const { Shape = this->length_p(0); } // Verify that dimensionality is 1 and then call Array::ok() virtual bool ok() const final override; protected: // Remove the degenerate axes from other and store result in this vector. // An exception is thrown if removing degenerate axes does not result // in a vector. virtual void doNonDegenerate(const Array &other, const IPosition &ignoreAxes) final override; virtual size_t fixedDimensionality() const final override { return 1; } private: Vector& assign_conforming_implementation(const Vector &v, std::false_type isCopyable); Vector& assign_conforming_implementation(const Vector &v, std::true_type isCopyable); // Helper functions for constructors. void initVector(const std::vector&, long long nr); // copy semantics // The following two constructors are used to make distinguish between // Vector(literal size, literal value) // and // Vector(iterator, iterator) template Vector(InputIterator startIter, InputIterator endIter, const Alloc& allocator, std::false_type /* T is not a literal */); template Vector(InputIterator startIter, InputIterator endIter, const Alloc& allocator, std::true_type /* T is literal */); }; } //#End namespace casacore #include "Vector.tcc" #include "Vector2.tcc" #endif