// ========================================================================== // SeqAn - The Library for Sequence Analysis // ========================================================================== // Copyright (c) 2006-2018, Knut Reinert, FU Berlin // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // * Neither the name of Knut Reinert or the FU Berlin nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // // ========================================================================== // Author: Ren� Rahn <rene.rahn@fu-berlin.de> // ========================================================================== // This file implements the class DPMatrix and its specialization // FullDPMatrix. The DPMatrix is a wrapper class around the Matrix<TValue,2> // class. Thus we can implement different specializations for the dp-matrix // that are used through the different dp-algorithms. For example, we need // a full dp matrix to store the traceback or the score for the Waterman- // Eggert algorithm, while for the other dp-algorithms we only need one // column vector to compute the scores. The default dp-matrix specialization // can be selected using a special meta-function. // ========================================================================== // TODO(holtgrew): Documentation in this header necessary or internal only? #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_MATRIX_H_ #define SEQAN_INCLUDE_SEQAN_ALIGN_DP_MATRIX_H_ namespace seqan { // ============================================================================ // Forwards // ============================================================================ template <typename TAlgorithm> struct DefaultScoreMatrixSpec_; // ============================================================================ // Tags, Classes, Enums // ============================================================================ // ---------------------------------------------------------------------------- // Tag MatrixMember // ---------------------------------------------------------------------------- struct DPMatrixMember_; typedef Tag<DPMatrixMember_> DPMatrixMember; // ---------------------------------------------------------------------------- // Tag SparseDPMatrix // ---------------------------------------------------------------------------- struct SparseDPMatrix_; typedef Tag<SparseDPMatrix_> SparseDPMatrix; // ---------------------------------------------------------------------------- // Tag FullDPMatrix // ---------------------------------------------------------------------------- struct FullDPMatrix_; typedef Tag<FullDPMatrix_> FullDPMatrix; // ---------------------------------------------------------------------------- // Enum DPMatrixDimension // ---------------------------------------------------------------------------- // Used to globally specify the correct dimension and the correct size of // dimension for the dp matrix. struct DPMatrixDimension_ { typedef unsigned int TValue; static const TValue VERTICAL = 0u; static const TValue HORIZONTAL = 1u; static const TValue DIMENSION = 2u; }; // ---------------------------------------------------------------------------- // Class DPMatrix_ // ---------------------------------------------------------------------------- // The dp matrix used as a score matrix and as a trace-back matrix. template <typename TValue, typename TMatrixSpec, typename THost = String<TValue> > class DPMatrix_ {}; // Default dp matrix implementation stores all cells of the dp matrix in the // underlying two-dimensional matrix. template <typename TValue, typename THost> class DPMatrix_<TValue, FullDPMatrix, THost> { public: typedef typename Member<DPMatrix_, DPMatrixMember>::Type TMatrix; Holder<TMatrix> data_host; // The host containing the actual matrix. DPMatrix_() : data_host() { create(data_host); } }; // ============================================================================ // Metafunctions // ============================================================================ // ---------------------------------------------------------------------------- // Metafunction DefaultScoreMatrixSpec_ // ---------------------------------------------------------------------------- // This meta-function determines the default specialization of dp matrix // based on the given algorithm tag. template <typename TAlgorithm> struct DefaultScoreMatrixSpec_ { typedef SparseDPMatrix Type; }; // TODO(rmaerker): Move to WatermanEggert implementation? template <> struct DefaultScoreMatrixSpec_<LocalAlignment_<WatermanEggert> > { typedef FullDPMatrix Type; }; // ---------------------------------------------------------------------------- // Metafunction DataHost_ // ---------------------------------------------------------------------------- // Returns the type of the underlying matrix. template <typename TValue, typename TMatrixSpec, typename THost> struct Member<DPMatrix_<TValue, TMatrixSpec, THost>, DPMatrixMember> { typedef Matrix<TValue, 2, THost> Type; }; template <typename TValue, typename TMatrixSpec, typename THost> struct Member<DPMatrix_<TValue, TMatrixSpec, THost> const, DPMatrixMember> { typedef Matrix<TValue, 2, THost> const Type; }; // ---------------------------------------------------------------------------- // Metafunction SizeArr_ // ---------------------------------------------------------------------------- // Returns the type of the containers to store the dimensions and the factors // in order to move properly in the matrix. template <typename TDPMatrix> struct SizeArr_ {}; template <typename TValue, typename TMatrixSpec, typename THost> struct SizeArr_<DPMatrix_<TValue, TMatrixSpec, THost> > { typedef DPMatrix_<TValue, TMatrixSpec, THost> TDPMatrix_; typedef typename Member<TDPMatrix_, DPMatrixMember>::Type TDataHost_; typedef typename SizeArr_<TDataHost_>::Type Type; }; template <typename TValue, typename TMatrixSpec, typename THost> struct SizeArr_<DPMatrix_<TValue, TMatrixSpec, THost> const> { typedef DPMatrix_<TValue, TMatrixSpec, THost> TDPMatrix_; typedef typename Member<TDPMatrix_, DPMatrixMember>::Type TDataHost_; typedef typename SizeArr_<TDataHost_>::Type const Type; }; // ---------------------------------------------------------------------------- // Metafunction Spec // ---------------------------------------------------------------------------- template <typename TValue, typename TMatrixSpec, typename THost> struct Spec<DPMatrix_<TValue, TMatrixSpec, THost> > { typedef TMatrixSpec Type; }; template <typename TValue, typename TMatrixSpec, typename THost> struct Spec<DPMatrix_<TValue, TMatrixSpec, THost> const>: Spec<DPMatrix_<TValue, TMatrixSpec, THost> >{}; // ---------------------------------------------------------------------------- // Metafunction Value // ---------------------------------------------------------------------------- template <typename TValue, typename TMatrixSpec, typename THost> struct Value<DPMatrix_<TValue, TMatrixSpec, THost> > { typedef TValue Type; }; template <typename TValue, typename TMatrixSpec, typename THost> struct Value<DPMatrix_<TValue, TMatrixSpec, THost> const> { typedef TValue const Type; }; // ---------------------------------------------------------------------------- // Metafunction Size // ---------------------------------------------------------------------------- template <typename TValue, typename TMatrixSpec, typename THost> struct Size<DPMatrix_<TValue, TMatrixSpec, THost> > { typedef typename DPMatrix_<TValue, TMatrixSpec, THost>::TMatrix TDataMatrix_; typedef typename Size<TDataMatrix_>::Type Type; }; // ---------------------------------------------------------------------------- // Metafunction Host // ---------------------------------------------------------------------------- template <typename TValue, typename TMatrixSpec, typename THost> struct Host<DPMatrix_<TValue, TMatrixSpec, THost> > { typedef THost Type; }; template <typename TValue, typename TMatrixSpec, typename THost> struct Host<DPMatrix_<TValue, TMatrixSpec, THost> const> { typedef THost const Type; }; // ---------------------------------------------------------------------------- // Metafunction Iterator // ---------------------------------------------------------------------------- // There are two iterator types. The standard iterator returns a // non-rooted iterator to the underlying vector of the hosted two-dimensional // matrix. The rooted iterator returns the iterator defined by the // hosted matrix object which is a position iterator. template <typename TValue, typename TMatrixSpec, typename THost> struct Iterator<DPMatrix_<TValue, TMatrixSpec, THost>, Standard> { typedef DPMatrix_<TValue, TMatrixSpec, THost> TDPMatrix_; typedef typename Host<TDPMatrix_>::Type THost_; typedef typename Iterator<THost_, Standard>::Type Type; }; template <typename TValue, typename TMatrixSpec, typename THost> struct Iterator<DPMatrix_<TValue, TMatrixSpec, THost> const, Standard> { typedef DPMatrix_<TValue, TMatrixSpec, THost> const TDPMatrix_; typedef typename Host<TDPMatrix_>::Type THost_; typedef typename Iterator<THost_ const, Standard>::Type Type; }; template <typename TValue, typename TMatrixSpec, typename THost> struct Iterator<DPMatrix_<TValue, TMatrixSpec, THost>, Rooted> { typedef DPMatrix_<TValue, TMatrixSpec, THost> TDPMatrix_; typedef typename Member<TDPMatrix_, DPMatrixMember>::Type TDataMatrix_; typedef typename Iterator<TDataMatrix_, Rooted>::Type Type; }; template <typename TValue, typename TMatrixSpec, typename THost> struct Iterator<DPMatrix_<TValue, TMatrixSpec, THost> const, Rooted> { typedef DPMatrix_<TValue, TMatrixSpec, THost> TDPMatrix_; typedef typename Member<TDPMatrix_, DPMatrixMember>::Type TDataMatrix_; typedef typename Iterator<TDataMatrix_ const, Rooted>::Type Type; }; // ============================================================================ // Functions // ============================================================================ // ---------------------------------------------------------------------------- // Function _checkCorrectDimension() // ---------------------------------------------------------------------------- // Checks whether a given value applies to the correct dimension. inline bool _checkCorrectDimension(DPMatrixDimension_::TValue dim) { return dim < DPMatrixDimension_::DIMENSION; } // ---------------------------------------------------------------------------- // Function _dataHost() // ---------------------------------------------------------------------------- // Returns a reference to the hosted matrix. template <typename TValue, typename TMatrixSpec, typename THost> inline Holder<typename Host<DPMatrix_<TValue, TMatrixSpec, THost> >::Type> & _dataHost(DPMatrix_<TValue, TMatrixSpec, THost> & dpMatrix) { return _dataHost(value(dpMatrix.data_host)); } template <typename TValue, typename TMatrixSpec, typename THost> inline Holder<typename Host<DPMatrix_<TValue, TMatrixSpec, THost> >::Type> const & _dataHost(DPMatrix_<TValue, TMatrixSpec, THost> const & dpMatrix) { return _dataHost(value(dpMatrix.data_host)); } // ---------------------------------------------------------------------------- // Function _dataLengths() // ---------------------------------------------------------------------------- // Returns a reference to the _dataLengths container of the hosted matrix. template <typename TValue, typename TMatrixSpec, typename THost> inline typename SizeArr_<DPMatrix_<TValue, TMatrixSpec, THost> >::Type & _dataLengths(DPMatrix_<TValue, TMatrixSpec, THost>&dpMatrix) { return _dataLengths(value(dpMatrix.data_host)); } template <typename TValue, typename TMatrixSpec, typename THost> inline typename SizeArr_<DPMatrix_<TValue, TMatrixSpec, THost> const>::Type & _dataLengths(DPMatrix_<TValue, TMatrixSpec, THost> const & dpMatrix) { return _dataLengths(value(dpMatrix.data_host)); } // ---------------------------------------------------------------------------- // Function _dataFactors() // ---------------------------------------------------------------------------- // Returns a reference to the _dataFactors container of the hosted matrix. template <typename TValue, typename TMatrixSpec, typename THost> inline typename SizeArr_<DPMatrix_<TValue, TMatrixSpec, THost> >::Type & _dataFactors(DPMatrix_<TValue, TMatrixSpec, THost>&dpMatrix) { return _dataFactors(value(dpMatrix.data_host)); } template <typename TValue, typename TMatrixSpec, typename THost> inline typename SizeArr_<DPMatrix_<TValue, TMatrixSpec, THost> const>::Type & _dataFactors(DPMatrix_<TValue, TMatrixSpec, THost> const & dpMatrix) { return _dataFactors(value(dpMatrix.data_host)); } // ---------------------------------------------------------------------------- // Function value() // ---------------------------------------------------------------------------- // Returns the value of the matrix at the given host position. template <typename TValue, typename TMatrixSpec, typename THost, typename TPosition> inline typename Reference<DPMatrix_<TValue, TMatrixSpec, THost> >::Type value(DPMatrix_<TValue, TMatrixSpec, THost> & dpMatrix, TPosition const & pos) { return value(value(dpMatrix.data_host), pos); } template <typename TValue, typename TMatrixSpec, typename THost, typename TPosition> inline typename Reference<DPMatrix_<TValue, TMatrixSpec, THost> const>::Type value(DPMatrix_<TValue, TMatrixSpec, THost> const & dpMatrix, TPosition const & pos) { return value(value(dpMatrix.data_host), pos); } // Returns the value of the matrix at the two given coordinates. template <typename TValue, typename TMatrixSpec, typename THost, typename TPositionV, typename TPositionH> inline typename Reference<DPMatrix_<TValue, TMatrixSpec, THost> >::Type value(DPMatrix_<TValue, TMatrixSpec, THost> & dpMatrix, TPositionV const & posDimV, TPositionH const & posDimH) { return value(value(dpMatrix.data_host), posDimV, posDimH); } template <typename TValue, typename TMatrixSpec, typename THost, typename TPositionV, typename TPositionH> inline typename Reference<DPMatrix_<TValue, TMatrixSpec, THost> const>::Type value(DPMatrix_<TValue, TMatrixSpec, THost> const & dpMatrix, TPositionV const & posDimV, TPositionH const & posDimH) { return value(value(dpMatrix.data_host), posDimV, posDimH); } // ---------------------------------------------------------------------------- // Function length() // ---------------------------------------------------------------------------- // Returns the length of a given dimension. template <typename TValue, typename TMatrixSpec, typename THost> inline typename Size<DPMatrix_<TValue, TMatrixSpec, THost> const>::Type length(DPMatrix_<TValue, TMatrixSpec, THost> const & dpMatrix, unsigned int dimension) { SEQAN_ASSERT(_checkCorrectDimension(dimension)); return length(value(dpMatrix.data_host), dimension); } // Returns the overall length of the underlying vector of the hosted matrix. template <typename TValue, typename TMatrixSpec, typename THost> inline typename Size<DPMatrix_<TValue, TMatrixSpec, THost> const>::Type length(DPMatrix_<TValue, TMatrixSpec, THost> const & dpMatrix) { return length(value(dpMatrix.data_host)); // Note that even if the dimensional lengths are set but the matrix was not resized // this function returns 0 or the previous length of the host before the resize. } // ---------------------------------------------------------------------------- // Function clear() // ---------------------------------------------------------------------------- template <typename TValue, typename TMatrixSpec, typename THost> inline void clear(DPMatrix_<TValue, TMatrixSpec, THost> & dpMatrix) { clear(_dataLengths(dpMatrix)); resize(_dataLengths(dpMatrix), 2, 0); clear(_dataFactors(dpMatrix)); resize(_dataFactors(dpMatrix), 2, 0); _dataFactors(dpMatrix)[DPMatrixDimension_::VERTICAL] = 1u; clear(host(dpMatrix)); } // ---------------------------------------------------------------------------- // Function empty() // ---------------------------------------------------------------------------- template <typename TValue, typename TMatrixSpec, typename THost> inline bool empty(DPMatrix_<TValue, TMatrixSpec, THost> const & dpMatrix) { return empty(host(dpMatrix)); } // ---------------------------------------------------------------------------- // Function setLength() // ---------------------------------------------------------------------------- // Sets the new length of a given dimension. template <typename TValue, typename TMatrixSpec, typename THost, typename TSize> inline void setLength(DPMatrix_<TValue, TMatrixSpec, THost> & dpMatrix, unsigned int dimension, TSize const & newLength) { SEQAN_ASSERT(_checkCorrectDimension(dimension)); setLength(value(dpMatrix.data_host), dimension, newLength); } // ---------------------------------------------------------------------------- // Function updateFactors() // ---------------------------------------------------------------------------- template <typename TValue, typename TMatrixSpec, typename THost> inline typename Size<DPMatrix_<TValue, TMatrixSpec, THost> >::Type updateFactors(DPMatrix_<TValue, TMatrixSpec, THost> & dpMatrix) { typedef typename Size<DPMatrix_<TValue, TMatrixSpec, THost> >::Type TSize; TSize factor_ = _dataFactors(dpMatrix)[0] * length(dpMatrix, 0); for (unsigned int i = 1; (factor_ > 0) && (i < dimension(value(dpMatrix.data_host))); ++i) { _dataFactors(dpMatrix)[i] = factor_; factor_ *= length(dpMatrix, i); } return factor_; } // ---------------------------------------------------------------------------- // Function resize() // ---------------------------------------------------------------------------- // Resizes the matrix. Note, the lengths of the dimensions have to be set before. template <typename TValue, typename TMatrixSpec, typename THost> inline void resize(DPMatrix_<TValue, TMatrixSpec, THost> & dpMatrix) { typedef typename Size<DPMatrix_<TValue, TMatrixSpec, THost> >::Type TSize; TSize reqSize = updateFactors(dpMatrix); if (reqSize > length(dpMatrix)) resize(host(dpMatrix), reqSize, Exact()); } template <typename TValue, typename TMatrixSpec, typename THost> inline void resize(DPMatrix_<TValue, TMatrixSpec, THost> & dpMatrix, TValue const & fillValue) { typedef typename Size<DPMatrix_<TValue, TMatrixSpec, THost> >::Type TSize; TSize reqSize = updateFactors(dpMatrix); if (reqSize > length(dpMatrix)) resize(host(dpMatrix), reqSize, fillValue, Exact()); } // ---------------------------------------------------------------------------- // Function begin() // ---------------------------------------------------------------------------- template <typename TValue, typename TMatrixSpec, typename THost> inline typename Iterator<DPMatrix_<TValue, TMatrixSpec, THost>, Standard>::Type begin(DPMatrix_<TValue, TMatrixSpec, THost> & dpMatrix, Standard) { return begin(host(dpMatrix)); } template <typename TValue, typename TMatrixSpec, typename THost> inline typename Iterator<DPMatrix_<TValue, TMatrixSpec, THost> const, Standard>::Type begin(DPMatrix_<TValue, TMatrixSpec, THost> const & dpMatrix, Standard) { return begin(host(dpMatrix)); } template <typename TValue, typename TMatrixSpec, typename THost> inline typename Iterator<DPMatrix_<TValue, TMatrixSpec, THost>, Rooted>::Type begin(DPMatrix_<TValue, TMatrixSpec, THost> & dpMatrix, Rooted) { return begin(value(dpMatrix.data_host)); } template <typename TValue, typename TMatrixSpec, typename THost> inline typename Iterator<DPMatrix_<TValue, TMatrixSpec, THost> const, Rooted>::Type begin(DPMatrix_<TValue, TMatrixSpec, THost> const & dpMatrix, Rooted) { return begin(value(dpMatrix.data_host)); } // ---------------------------------------------------------------------------- // Function end() // ---------------------------------------------------------------------------- template <typename TValue, typename TMatrixSpec, typename THost> inline typename Iterator<DPMatrix_<TValue, TMatrixSpec, THost>, Standard>::Type end(DPMatrix_<TValue, TMatrixSpec, THost> & dpMatrix, Standard) { return end(host(dpMatrix)); } template <typename TValue, typename TMatrixSpec, typename THost> inline typename Iterator<DPMatrix_<TValue, TMatrixSpec, THost> const, Standard>::Type end(DPMatrix_<TValue, TMatrixSpec, THost> const & dpMatrix, Standard) { return end(host(dpMatrix)); } template <typename TValue, typename TMatrixSpec, typename THost> inline typename Iterator<DPMatrix_<TValue, TMatrixSpec, THost>, Rooted>::Type end(DPMatrix_<TValue, TMatrixSpec, THost> & dpMatrix, Rooted) { return end(value(dpMatrix.data_host)); } template <typename TValue, typename TMatrixSpec, typename THost> inline typename Iterator<DPMatrix_<TValue, TMatrixSpec, THost>, Rooted>::Type end(DPMatrix_<TValue, TMatrixSpec, THost> const & dpMatrix, Rooted) { return end(value(dpMatrix.data_host)); } // ---------------------------------------------------------------------------- // Function coordinate() // ---------------------------------------------------------------------------- // Returns the coordinate of a host positio in a given dimension. template <typename TValue, typename THost, typename TPosition> inline typename Position<DPMatrix_<TValue, FullDPMatrix, THost> >::Type coordinate(DPMatrix_<TValue, FullDPMatrix, THost> const & dpMatrix, TPosition hostPos, typename DPMatrixDimension_::TValue dimension) { return coordinate(value(dpMatrix.data_host), hostPos, dimension); } // ---------------------------------------------------------------------------- // Function toGlobalPosition() // ---------------------------------------------------------------------------- // Returns the current position of the navigator within the matrix. template <typename TValue, typename THost, typename TPosH, typename TPosV> inline typename Position<DPMatrix_<TValue, FullDPMatrix, THost> >::Type toGlobalPosition(DPMatrix_<TValue, FullDPMatrix, THost> const & dpMatrix, TPosH const horizontalCoordinate, TPosV const verticalCoordinate) { return horizontalCoordinate * length(dpMatrix, DPMatrixDimension_::VERTICAL) + verticalCoordinate; } } // namespace seqan #endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_MATRIX_H_