/* -*- 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: vctDynamicMatrixOwner.h,v 1.19 2007/04/26 19:33:57 anton Exp $ Author(s): Ofri Sadowsky, Anton Deguet Created on: 2004-07-01 (C) Copyright 2004-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 _vctDynamicMatrixOwner_h #define _vctDynamicMatrixOwner_h /*! \file \brief Declaration of vctDynamicMatrixOwner */ #include /*! This templated class owns a dynamically allocated array, but does not provide any other operations */ template class vctDynamicMatrixOwner { public: /* define most types from vctContainerTraits */ VCT_CONTAINER_TRAITS_TYPEDEFS(_elementType); /* iterators are container specific */ typedef vctVarStrideMatrixConstIterator const_iterator; typedef vctVarStrideMatrixConstIterator const_reverse_iterator; typedef vctVarStrideMatrixIterator iterator; typedef vctVarStrideMatrixIterator reverse_iterator; vctDynamicMatrixOwner(): Rows(0), Cols(0), RowMajor(VCT_DEFAULT_STORAGE), Data(0) {} vctDynamicMatrixOwner(size_type rows, size_type cols, bool rowMajor = VCT_DEFAULT_STORAGE) : Rows(0) , Cols(0) , RowMajor(0) , Data(0) { SetSize(rows, cols, rowMajor); } ~vctDynamicMatrixOwner() { Disown(); } size_type size(void) const { return Rows * Cols; } size_type rows(void) const { return Rows; } size_type cols(void) const { return Cols; } difference_type row_stride(void) const { return RowMajor ? Cols : 1; } difference_type col_stride(void) const { return RowMajor ? 1 : Rows; } pointer Pointer(index_type rowIndex, index_type colIndex) { return Data + rowIndex * row_stride() + colIndex * col_stride(); } pointer Pointer(void) { return Data; } const_pointer Pointer(index_type rowIndex, index_type colIndex) const { return Data + rowIndex * row_stride() + colIndex * col_stride(); } const_pointer Pointer(void) const { return Data; } const_iterator begin(void) const { return const_iterator(Data, col_stride(), cols(), row_stride()); } const_iterator end(void) const { return const_iterator(Data, col_stride(), cols(), row_stride()) + rows() * cols(); } iterator begin(void) { return iterator(Data, col_stride(), cols(), row_stride()); } iterator end(void) { return iterator(Data, col_stride(), cols(), row_stride()) + rows() * cols(); } const_reverse_iterator rbegin(void) const { return const_reverse_iterator(Data + row_stride() * (rows() - 1) + col_stride() * (cols() - 1), -col_stride(), cols(), -row_stride()); } const_reverse_iterator rend(void) const { return const_reverse_iterator(Data - row_stride() + col_stride() * (cols() - 1), -col_stride(), cols(), -row_stride()); } reverse_iterator rbegin(void) { return reverse_iterator(Data + row_stride() * (rows() - 1) + col_stride() * (cols() - 1), -col_stride(), cols(), -row_stride()); } reverse_iterator rend(void) { return reverse_iterator(Data - row_stride() + col_stride() * (cols() - 1), -col_stride(), cols(), -row_stride()); } /*! Non-preserving resize operation. This method discards of all the current data of the dynamic array and allocates new space in the requested size. \note If the storage order and the sizes (both rows and columns) are unchanged, this method does nothing. \note If the size is set to zero, the data pointer is set to null (0). */ void SetSize(size_type rows, size_type cols, bool rowMajor) { if ((rows == Rows) && (cols == Cols) && (rowMajor == RowMajor)) return; Disown(); const size_type totalSize = rows * cols; Own(rows, cols, rowMajor, (totalSize == 0) ? 0 : new value_type[totalSize]); } /*! Data preserving resize operation. This method allocates a buffer of the input size and copies all possible old buffer elements to the new buffer. If the new buffer is larger than the old, the tail elements are initialized with a default constructor. \note If the storage order and the sizes (both rows and columns) are unchanged, this method does nothing. \note This method doesn't allow to change the storage order of the elements (i.e. stays either row or column major). \note If the size is set to zero, the data pointer is set to null (0). */ void resize(size_type rows, size_type cols) { if ((rows == Rows) && (cols == Cols)) return; const size_type oldRows = Rows; const size_type oldCols = Cols; value_type * oldData = Release(); SetSize(rows, cols, RowMajor); const size_type minRows = std::min(oldRows, rows); const size_type minCols = std::min(oldCols, cols); const difference_type oldRowStride = RowMajor ? oldCols : 1; const difference_type oldColStride = RowMajor ? 1 : oldRows; size_type rowIndex, colIndex; for (rowIndex = 0; rowIndex < minRows; ++rowIndex) for (colIndex = 0; colIndex < minCols; ++colIndex) Data[rowIndex * row_stride() + colIndex * col_stride()] = oldData[rowIndex * oldRowStride + colIndex * oldColStride]; delete[] oldData; } /*! Release the currently owned data pointer from being owned. Reset this owner's data pointer and size to zero. Return the old data pointer without freeing memory. */ value_type * Release() { value_type * oldData = Data; Data = 0; Rows = 0; Cols = 0; RowMajor = VCT_DEFAULT_STORAGE; return oldData; } /*! Have this owner take ownership of a new data pointer. Return the old data pointer without freeing memory. \note This method returns a pointer to the previously owned memory block but doesn't tell if the old block was row or column major nor the size of the block. */ value_type * Own(size_type rows, size_type cols, bool rowMajor, value_type * data) { value_type * oldData = Data; Rows = rows; Cols = cols; RowMajor = rowMajor; Data = data; return oldData; } /*! Free the memory allocated for the data pointer. Reset data pointer and size to zero. */ void Disown(void) { delete[] Data; Rows = 0; Cols = 0; Data = 0; } inline bool IsColMajor(void) const { return !RowMajor; } inline bool IsRowMajor(void) const { return RowMajor; } inline bool StorageOrder(void) const { return RowMajor; } protected: size_type Rows; size_type Cols; bool RowMajor; value_type* Data; }; #endif // _vctDynamicMatrixOwner_h // **************************************************************************** // Change History // **************************************************************************** // // $Log: vctDynamicMatrixOwner.h,v $ // Revision 1.19 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.18 2007/04/09 15:01:05 ofri // vctDynamic[Vector|Matrix|NArray]Owner: // 1) Created a uniform implementation of constructors and SetSize methods, // following ticket #274. // 2) Removed obsolete constructor (#275) // 3) Cosmetic changes in the NArray owner. // // Revision 1.17 2007/04/03 18:26:06 anton // vctDynamicMatrixOwner.h: For both ctor and SetSize(), handles cases when total // size is zero (do not perform "new"). See #125 // // Revision 1.16 2006/11/20 20:33:20 anton // Licensing: Applied new license to cisstCommon, cisstVector, cisstNumerical, // cisstInteractive, cisstImage and cisstOSAbstraction. // // Revision 1.15 2006/11/08 04:28:20 anton // vctDynamic{Vector,Matrix}Owner: Changed behavior of SetSize() and resize() // so that if the size is zero, the data pointer is also 0 (aka null). // // Revision 1.14 2006/04/26 19:51:21 anton // vctDynamicMatrix: Correction for bug #221. This should work well for matrices // using vctDynamicMatrixOwner. For matrices using existing memory, i.e. // vctDynamicMatrixRefOwner, we need to redefine the specifications and add test // cases. // // Revision 1.13 2005/09/26 15:41:47 anton // cisst: Added modelines for emacs and vi. // // Revision 1.12 2005/07/28 20:54:13 anton // vctDynamic{Vector,Matrix}Owner: Modified SetSize() and resize() to do // nothing if the size of container is unchanged. // // Revision 1.11 2005/05/19 19:29:01 anton // cisst libs: Added the license to cisstCommon and cisstVector // // Revision 1.10 2005/02/09 15:30:06 ofri // Resovling .NET compiler warning in vctDynamicMatrixOwner::resize -- signed type // mismatch. // // Revision 1.9 2004/12/01 16:42:20 anton // cisstVector: Modified the signature of Pointer methods for matrices. We now // have two signature, Pointer(void) and Pointer(row, col) with no default value // to avoid the ambiguous Pointer(index). See ticket #93. // // Revision 1.8 2004/11/29 17:31:28 anton // cisstVector: Major corrections for matrices reverse iterators. Correction // of the - operator which now takes into account the current column position. // // Revision 1.7 2004/11/11 20:35:46 anton // cisstVector: *: Added a vctContainerTraits to centralize the declarations // of size_type, difference_type, reference, const_reference, etc. *: All // iterators are now derived from std::iterator. *: Added some missing typedef // for iterators. // // Revision 1.6 2004/11/03 22:26:12 anton // cisstVector: Better support of storage order. Added VCT_COL_MAJOR, // VCT_ROW_MAJOR and VCT_DEFAULT_STORAGE as well as the methods IsColMajor(), // IsRowMajor(), IsCompact() and IsFortran(). // // Revision 1.5 2004/10/25 13:52:05 anton // Doxygen documentation: Cleanup all the useless \ingroup. // // Revision 1.4 2004/10/19 20:50:50 anton // cisstVector: Preliminary support for different storage orders (i.e. row // major by default, column major if specified). This has been implemented // for the vctFixedSizeMatrix as well as the vctDynamicMatrix. We tested the // code by simply changinf the default and all current tests passed. See // ticket #75 re. vctFortranMatrix. // // Revision 1.3 2004/09/09 14:03:32 ofri // vctDynamicMatrixOwner: Bug fix in method resize(). See #57 // // Revision 1.2 2004/08/16 19:19:49 anton // cisstVector: Replaced a couple of "value_type *" by typedefed "pointer" // and "const value_type *" by "const_pointer". // // Revision 1.1 2004/08/04 21:11:10 anton // cisstVector: Added preliminary version of dynamic matrices. Lots of work // is still required, this code is not ready to be used. // // // ****************************************************************************