/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* ex: set filetype=cpp softtabstop=4 shiftwidth=4 tabstop=4 cindent expandtab: */ /* $Id: vctDynamicNArray.h,v 1.6 2007/05/30 02:44:49 anton Exp $ Author(s): Daniel Li Created on: 2006-07-10 (C) Copyright 2006-2007 Johns Hopkins University (JHU), All Rights Reserved. --- begin cisst license - do not edit --- This software is provided "as is" under an open source license, with no warranty. The complete license can be found in license.txt and http://www.cisst.org/cisst/license.txt. --- end cisst license --- */ #ifndef _vctDynamicNArray_h #define _vctDynamicNArray_h /*! \file \brief Declaration of vctDynamicNArray */ #include #include #include /*! \ingroup cisstVector \brief An nArray object of dynamic size. This class defines a nArray object of dynamic size with memory allocation. The algebraic operations are mostly inherited from the base classes vctDynamicNArrayBase and vctDynamicConstNArrayBase. Here, we will briefly describe the specific properties of vctDynamicNArray, with a few usage examples.
  1. The class is templated by its element type, that is, the nArray element. Normally, the element should be an arithmetic type, that is, support all the standard arithmetic operations: +, -, *, /, =, ==, <, >, <=, >=, ...
  2. The class uses dynamically allocated memory, and, more importantly, \em owns the memory. That is, a vctDynamicNArray object automatically frees the allocated memory it owns when it is destroyed.
  3. To allocate the memory, use one of the following operations. \code // define a typical element type typedef double ElementType; // the dimension can be set to any value at any time before creating // the nArray dimension_type dims = 5; // constructor allocation vctDynamicNArray a1(dims); // Create an empty nArray and later allocate memory. vctDynamicNArray m2; m2.SetSize(matrixRows, matrixCols); // Create an nArray of some size and then change it. // This operation does not preserve any elements in the resized // matrix vctDynamicNArray m3(3 * matrixRows, 3 * matrixCols); m3.SetSize(2 * matrixRows, 2 * matrixCols); // resize an nArray and keep as many elements as possible. m3.resize(matrixRows, matrixCols); // Store an algebraic result to a new matrix. In this case, // memory is allocated by the algebraic operation, and then // attached to the matrix object. vctDynamicNArray m4 = m3 - m2; \endcode
  4. The default storage order is row first. This can be modified using the different constructors as well as the method SetSize with the flags #VCT_ROW_MAJOR or #VCT_COL_MAJOR. \code // 12 by 7 matrix stored column first vctDynamicNArray m1(12, 7, VCT_COL_MAJOR); // a similar matrix filled with zeroes vctDynamicNArray m1(12, 7, 0.0, VCT_COL_MAJOR); // resize the matrix and change its storage order m1.SetSize(5, 7, VCT_ROW_MAJOR); \endcode
  5. Matrix assignment can be facilitated through the Assign method (defined in the base class) or as follows. \code // Initialize all elements to the same value vctDynamicNArray v5(matrixRows, matrixCols, 2.0); // Initialize the elements by specific values. NOTE: All the // arguments MUST be of type ElementType vctDynamicNArray matrix(2, 4); matrix.Assign(7.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0); // correct matrix.Assign(7, 1, 2, 3, 4, 5, 6, 7); // WRONG, missing dot // Assign one matrix to another. vctDynamicNArray matrixInt; matrixInt.Assign(matrix); matrixInt = matrix; // same operation \endcode
A few more notes.
  • The elements lie in contiguous increasing memory addresses.
  • There is no direct way of ``disowning'' a vctDynamicNArray, that is taking ownership of its memory.
  • When a function returns an allocating dynamic matrix object, it is better to return a vctReturnDynamicNArray, which is a helper class designed for transfering the ownership of the allocated memory without reallocation.
\param _elementType the type of an element in the nArray \sa vctDynamicNArrayBase vctDynamicConstNArrayBase */ template class vctDynamicNArray : public vctDynamicNArrayBase, _elementType, _dimension> { friend class vctReturnDynamicNArray<_elementType, _dimension>; public: /* define most types from vctContainerTraits and vctNArrayTraits */ VCT_CONTAINER_TRAITS_TYPEDEFS(_elementType); VCT_NARRAY_TRAITS_TYPEDEFS(_dimension); typedef vctDynamicNArrayBase, _elementType, _dimension> BaseType; typedef vctDynamicNArray<_elementType, _dimension> ThisType; /*! Default constructor. Initialize an empty nArray. */ vctDynamicNArray() // The default initialization of vctDynamicNArrayOwner is empty. {} /*! Constructor: Create an nArray of the specified sizes. Elements initialized with default constructor. */ vctDynamicNArray(const nsize_type & sizes) { this->NArray.SetSize(sizes); } /*! Constructor: Create an nArray of the specified size and assign all elements a specific value. */ vctDynamicNArray(const nsize_type & sizes, value_type value) { this->NArray.SetSize(sizes); SetAll(value); } /*! Special copy constructor: Take ownership of the data of a temporary nArray object of type vctReturnDynamicNArray. Disown the other nArray. */ vctDynamicNArray(const vctReturnDynamicNArray & otherNArray); /*! Copy constructor: Allocate memory to store a copy of the other nArray, and copy the elements of the other matrix to this nArray. */ vctDynamicNArray(const ThisType & otherNArray) { SetSize(otherNArray.sizes()); this->Assign(otherNArray); } /*! Copy constructor: Allocate memory and copy all the elements from the other nArray. */ template vctDynamicNArray(const vctDynamicConstNArrayBase<_otherNArrayOwnerType, value_type, _dimension> & otherNArray) { SetSize(otherNArray.sizes()); this->Assign(otherNArray); } /*! Copy constructor: Allocate memory and copy all the elements from the other nArray. This constructor can also be used for type conversions. */ template explicit vctDynamicNArray(const vctDynamicConstNArrayBase<_otherNArrayOwnerType, _otherNArrayElementType, _dimension> & otherNArray) { SetSize(otherNArray.sizes()); this->Assign(otherNArray); } /*! Assignment from an nArray to this nArray. The operation discards the old memory allocated for this nArray and allocates new memory the size of the input nArray. Then the elements of the input nArray are copied into this nArray. */ template ThisType & operator = (const vctDynamicConstNArrayBase<__nArrayOwnerType, __elementType, _dimension> & otherNArray) { SetSize(otherNArray.sizes()); this->Assign(otherNArray); return *this; } /*! Equals operator: Assignment from a vctDynamicNArray to this nArray (also a vctDynamicNArray). The operation discards the old memory allocated for this nArray and allocates new memory the size of the input vctDynamicNArray. Then the elements of the input vctDynamicNArray are copied into this nArray. */ ThisType & operator = (const ThisType & otherNArray) { SetSize(otherNArray.sizes()); this->Assign(otherNArray); return *this; } /*! Assignment from a transitional vctReturnDynamicNArray to a vctDynamicNArray variable. This specialized operation does not perform any element copy. Instead it transfers ownership of the data from the other nArray to this nArray, and disowns the other nArray. The right hand side operand must be a temporary object returned, e.g., from a function or overloaded operator. \todo This operator needs some revisions. */ ThisType & operator = (const vctReturnDynamicNArray & otherNArray); /*! Assignment of a scalar to all elements. See also SetAll. */ inline ThisType & operator = (const value_type & value) { this->SetAll(value); return *this; } /*! Destructive size change. Change the size to the specified size. Discard all of the old values. */ //@{ void SetSize(const nsize_type & sizes) { this->NArray.SetSize(sizes); } //@} }; /*! Class vctReturnDynamicNArray is specialized to store a temporary nArray object by transferring ownership. An object of this class has all the methods inherited from vctDynamicNArray, but can only be constructed in one way -- taking the ownership from another vctDynamicNArray (or vctReturnDynamicNArray) object. In turn, when an assignment occurs from a vctReturnDynamicNArray to a vctDynamicNArray (or likewise construction), the LHS vctDynamicNArray strips this object from the ownership of the data. Use this class only when you want to return a newly created dynamic matrix from a function, without going through memory allocation and deallocation. Never use it on an object that is going to remain in scope after constructing the vctReturnDynamicNArray. */ template class vctReturnDynamicNArray : public vctDynamicNArray<_elementType, _dimension> { public: VCT_CONTAINER_TRAITS_TYPEDEFS(_elementType); VCT_NARRAY_TRAITS_TYPEDEFS(_dimension); /*! Base type of vctReturnDynamicNArray. */ typedef vctDynamicNArray<_elementType, _dimension> BaseType; explicit vctReturnDynamicNArray(const BaseType & other) { BaseType & nonConstOther = const_cast(other); // if we don't save it in a variable, it will be destroyed in the Release operation const nsize_type sizes = other.sizes(); this->NArray.Own(sizes, nonConstOther.NArray.Release()); } }; // implementation of the special copy constructor of vctDynamicNArray template vctDynamicNArray<_elementType, _dimension>::vctDynamicNArray(const vctReturnDynamicNArray<_elementType, _dimension> & other) { vctReturnDynamicNArray<_elementType, _dimension> & nonConstOther = const_cast< vctReturnDynamicNArray<_elementType, _dimension> & >(other); // if we don't save it in a variable, it will be destroyed in the Release operation const nsize_type sizes = other.sizes(); this->NArray.Own(sizes, nonConstOther.NArray.Release()); } // implementation of the special assignment operator from vctReturnDynamicNArray to vctDynamicNArray template vctDynamicNArray<_elementType, _dimension> & vctDynamicNArray<_elementType, _dimension>::operator = (const vctReturnDynamicNArray<_elementType, _dimension> & other) { vctReturnDynamicNArray<_elementType, _dimension> & nonConstOther = const_cast< vctReturnDynamicNArray<_elementType, _dimension> & >(other); // if we don't save it in a variable, it will be destroyed in the Release operation const nsize_type sizes = other.sizes(); this->NArray.clear(); this->NArray.Own(sizes, nonConstOther.NArray.Release()); return *this; } /*! \name Elementwise operations between nArrays. */ //@{ /*! Operation between nArrays (same size). \param inputNArray1 The first operand of the binary operation. \param inputNArray2 The second operand of the binary operation. \return The nArray result of \f$op(nArray1, nArray2)\f$. */ template vctReturnDynamicNArray<_elementType, _dimension> operator + (const vctDynamicConstNArrayBase<_nArrayOwnerType1, _elementType, _dimension> & inputNArray1, const vctDynamicConstNArrayBase<_nArrayOwnerType2, _elementType, _dimension> & inputNArray2) { typedef _elementType value_type; vctDynamicNArray resultStorage(inputNArray1); resultStorage.Add(inputNArray2); return vctReturnDynamicNArray(resultStorage); } /* documented above */ template vctReturnDynamicNArray<_elementType, _dimension> operator - (const vctDynamicConstNArrayBase<_nArrayOwnerType1, _elementType, _dimension> & inputNArray1, const vctDynamicConstNArrayBase<_nArrayOwnerType2, _elementType, _dimension> & inputNArray2) { typedef _elementType value_type; vctDynamicNArray resultStorage(inputNArray1); resultStorage.Subtract(inputNArray2); return vctReturnDynamicNArray(resultStorage); } //@} /*! \name Elementwise operations between an nArray and a scalar. */ //@{ /*! Operation between an nArray and a scalar. \param inputNArray The first operand of the binary operation. \param inputScalar The second operand of the binary operation. \return The nArray result of \f$op(nArray, scalar)\f$. */ template vctReturnDynamicNArray<_elementType, _dimension> operator + (const vctDynamicConstNArrayBase<_nArrayOwnerType, _elementType, _dimension> & inputNArray, const _elementType & inputScalar) { typedef _elementType value_type; vctDynamicNArray resultStorage(inputNArray); resultStorage.Add(inputScalar); return vctReturnDynamicNArray(resultStorage); } /* documented above */ template vctReturnDynamicNArray<_elementType, _dimension> operator - (const vctDynamicConstNArrayBase<_nArrayOwnerType, _elementType, _dimension> & inputNArray, const _elementType & inputScalar) { typedef _elementType value_type; vctDynamicNArray resultStorage(inputNArray); resultStorage.Subtract(inputScalar); return vctReturnDynamicNArray(resultStorage); } /* documented above */ template vctReturnDynamicNArray<_elementType, _dimension> operator * (const vctDynamicConstNArrayBase<_nArrayOwnerType, _elementType, _dimension> & inputNArray, const _elementType & inputScalar) { typedef _elementType value_type; vctDynamicNArray resultStorage(inputNArray); resultStorage.Multiply(inputScalar); return vctReturnDynamicNArray(resultStorage); } /* documented above */ template vctReturnDynamicNArray<_elementType, _dimension> operator / (const vctDynamicConstNArrayBase<_nArrayOwnerType, _elementType, _dimension> & inputNArray, const _elementType & inputScalar) { typedef _elementType value_type; vctDynamicNArray resultStorage(inputNArray); resultStorage.Divide(inputScalar); return vctReturnDynamicNArray(resultStorage); } //@} /*! \name Elementwise operations between a scalar and an nArray. */ //@{ /*! Operation between a scalar and an nArray. \param inputScalar The first operand of the binary operation. \param inputNArray The second operand of the binary operation. \return The nArray result of \f$op(scalar, nArray)\f$. */ template vctReturnDynamicNArray<_elementType, _dimension> operator + (const _elementType & inputScalar, const vctDynamicConstNArrayBase<_nArrayOwnerType, _elementType, _dimension> & inputNArray) { typedef _elementType value_type; vctDynamicNArray resultStorage(inputNArray.sizes()); resultStorage.SumOf(inputScalar, inputNArray); return vctReturnDynamicNArray(resultStorage); } /* documented above */ template vctReturnDynamicNArray<_elementType, _dimension> operator - (const _elementType & inputScalar, const vctDynamicConstNArrayBase<_nArrayOwnerType, _elementType, _dimension> & inputNArray) { typedef _elementType value_type; vctDynamicNArray resultStorage(inputNArray.sizes()); resultStorage.DifferenceOf(inputScalar, inputNArray); return vctReturnDynamicNArray(resultStorage); } /* documented above */ template vctReturnDynamicNArray<_elementType, _dimension> operator * (const _elementType & inputScalar, const vctDynamicConstNArrayBase<_nArrayOwnerType, _elementType, _dimension> & inputNArray) { typedef _elementType value_type; vctDynamicNArray resultStorage(inputNArray.sizes()); resultStorage.ProductOf(inputScalar, inputNArray); return vctReturnDynamicNArray(resultStorage); } /* documented above */ template vctReturnDynamicNArray<_elementType, _dimension> operator / (const _elementType & inputScalar, const vctDynamicConstNArrayBase<_nArrayOwnerType, _elementType, _dimension> & inputNArray) { typedef _elementType value_type; vctDynamicNArray resultStorage(inputNArray.sizes()); resultStorage.RatioOf(inputScalar, inputNArray); return vctReturnDynamicNArray(resultStorage); } //@} /*! \name Elementwise operations on an nArray. */ //@{ /*! Unary operation on an nArray. \param inputNArray The operand of the unary operation \return The nArray result of \f$op(nArray)\f$. */ template vctReturnDynamicNArray<_elementType, _dimension> operator - (const vctDynamicConstNArrayBase<_nArrayOwnerType, _elementType, _dimension> & inputNArray) { typedef _elementType value_type; vctDynamicNArray resultStorage(inputNArray.sizes()); resultStorage.NegationOf(inputNArray); return vctReturnDynamicNArray(resultStorage); } //@} #ifndef DOXYGEN template vctReturnDynamicNArray<_elementType, _dimension> operator * (const vctDynamicConstNArrayBase<_nArrayOwnerType1, _elementType, _dimension> & inputNArray1, const vctDynamicConstNArrayBase<_nArrayOwnerType2, _elementType, _dimension> & inputNArray2) { typedef _elementType value_type; vctDynamicNArray resultStorage(inputNArray1.sizes()); resultStorage.ProductOf(inputNArray1, inputNArray2); return vctReturnDynamicNArray(resultStorage); } /* Methods declared previously and implemented here because they require vctReturnDynamicNArray */ /* documented in class vctDynamicConstNArrayBase */ template inline typename vctDynamicConstNArrayBase<_nArrayOwnerType, _elementType, _dimension>::NArrayValueType vctDynamicConstNArrayBase<_nArrayOwnerType, _elementType, _dimension>::Abs(void) const { typedef _elementType value_type; vctDynamicNArray resultStorage(this->sizes()); vctDynamicNArrayLoopEngines<_dimension>::template NoNi::AbsValue>:: Run(resultStorage, *this); return vctReturnDynamicNArray(resultStorage); } /* documented in class vctDynamicConstNArrayBase */ template inline typename vctDynamicConstNArrayBase<_nArrayOwnerType, _elementType, _dimension>::NArrayValueType vctDynamicConstNArrayBase<_nArrayOwnerType, _elementType, _dimension>::Negation(void) const { typedef _elementType value_type; vctDynamicNArray resultStorage(this->sizes()); vctDynamicNArrayLoopEngines<_dimension>::template NoNi::Negation>:: Run(resultStorage, *this); return vctReturnDynamicNArray(resultStorage); } /* documented in class vctDynamicConstNArrayBase */ template inline typename vctDynamicConstNArrayBase<_nArrayOwnerType, _elementType, _dimension>::NArrayValueType vctDynamicConstNArrayBase<_nArrayOwnerType, _elementType, _dimension>::Floor(void) const { typedef _elementType value_type; vctDynamicNArray resultStorage(this->sizes()); vctDynamicNArrayLoopEngines<_dimension>::template NoNi::Floor>:: Run(resultStorage, *this); return vctReturnDynamicNArray(resultStorage); } /* documented in class vctDynamicConstNArrayBase */ template inline typename vctDynamicConstNArrayBase<_nArrayOwnerType, _elementType, _dimension>::NArrayValueType vctDynamicConstNArrayBase<_nArrayOwnerType, _elementType, _dimension>::Ceil(void) const { typedef _elementType value_type; vctDynamicNArray resultStorage(this->sizes()); vctDynamicNArrayLoopEngines<_dimension>::template NoNi::Ceil>:: Run(resultStorage, *this); return vctReturnDynamicNArray(resultStorage); } /* Documented in class vctDynamicConstNArrayBase */ template inline vctReturnDynamicNArray vctDynamicNArrayElementwiseCompareNArray(const vctDynamicConstNArrayBase<_nArrayOwnerType, _elementType, _dimension> & nArray1, const vctDynamicConstNArrayBase<_nArrayOwnerType, _elementType, _dimension> & nArray2) { vctDynamicNArray result(nArray1.sizes()); vctDynamicNArrayLoopEngines<_dimension>::template NoNiNi<_elementOperationType>::Run(result, nArray1, nArray2); return vctReturnDynamicNArray(result); } /* documented in class vctDynamicConstNArrayBase */ template inline vctReturnDynamicNArray vctDynamicNArrayElementwiseCompareScalar(const vctDynamicConstNArrayBase<_nArrayOwnerType, _elementType, _dimension> & nArray, const _elementType & scalar) { vctDynamicNArray result(nArray.sizes()); vctDynamicNArrayLoopEngines<_dimension>::template NoNiSi<_elementOperationType>::Run(result, nArray, scalar); return vctReturnDynamicNArray(result); } /* documented in class vctDynamicConstNArrayBase */ template inline vctDynamicNArrayRef<_elementType, _dimension - 1> vctDynamicNArrayNArraySlice(vctDynamicNArrayBase<_nArrayOwnerType, _elementType, _dimension> & input, unsigned int dimension, unsigned int index) { vctDynamicNArrayRef<_elementType, _dimension - 1> slice; slice.SliceOf(input, dimension, index); return slice; } /* documented in class vctDynamicConstNArrayBase */ template inline _elementType & vctDynamicNArrayElementSlice(vctDynamicNArrayBase<_nArrayOwnerType, _elementType, 1> & input, unsigned int index) { return input.Element(vctFixedSizeVector(index)); } /* documented in class vctDynamicConstNArrayBase */ template inline vctDynamicConstNArrayRef<_elementType, _dimension - 1> vctDynamicNArrayConstNArraySlice(const vctDynamicConstNArrayBase<_nArrayOwnerType, _elementType, _dimension> & input, unsigned int dimension, unsigned int index) { vctDynamicConstNArrayRef<_elementType, _dimension - 1> slice; slice.SliceOf(input, dimension, index); return slice; } /* documented in class vctDynamicConstNArrayBase */ template inline const _elementType & vctDynamicNArrayConstElementSlice(const vctDynamicConstNArrayBase<_nArrayOwnerType, _elementType, 1> & input, unsigned int index) { return input.Element(vctFixedSizeVector(index)); } #endif // DOXYGEN #endif // _vctDynamicNArray_h // **************************************************************************** // Change History // **************************************************************************** // // $Log: vctDynamicNArray.h,v $ // Revision 1.6 2007/05/30 02:44:49 anton // cisstVector: Added non-explicit copy constructor to all dynamic containers // (explicit ctors are provided for type conversion). // // Revision 1.5 2007/05/02 19:19:06 ofri // vctDynamic[Vector|Matrix|NArray] : Changed the constructor from another // vector|... so that it enables element type conversions. // // Revision 1.4 2007/04/26 19:33:57 anton // All files in libraries: Applied new license text, separate copyright and // updated dates, added standard header where missing. // // Revision 1.3 2007/03/08 04:29:25 anton // cisstVector NArray: Now templated by dimension (see #258). Added template // specialization for slices of dimension 1 NArray to return value_type. Used // Ofri's implementation of IncrementPointer() in loop engines (previous one did // not handle more than dimension 3). Also renamed DimSize, DimStride and // Dimension to size(d), stride(d), and dimensioni (for STL flavor). // // Revision 1.2 2007/01/23 21:09:24 anton // cisstVector NArray: Removed code and comments related to transpose and eye // since these have no real utility for NArrays (see ticket #255) // // Revision 1.1 2006/12/09 04:13:25 anton // cisstVector: Imported code for NArray from Daniel Li with minor cleanup // for license, dos2unix, a few renamed methods and port to gcc. // // // ****************************************************************************