//# 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