/* * MatSample.hpp, part of LatAnalyze 3 * * Copyright (C) 2013 - 2015 Antonin Portelli * * LatAnalyze 3 is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * LatAnalyze 3 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with LatAnalyze 3. If not, see . */ #ifndef Latan_MatSample_hpp_ #define Latan_MatSample_hpp_ #include #include #include #include BEGIN_LATAN_NAMESPACE /****************************************************************************** * matrix sample class * ******************************************************************************/ #define SCAL_OP_RETURN(op, s, x) s.unaryExpr(\ std::bind(MatSample::scalar##op,\ std::placeholders::_1, x)) template class MatSample: public Sample>, public IoObject { public: // block type template template class BlockTemplate { private: typedef typename std::remove_const::type NonConstType; public: // constructors BlockTemplate(S &sample, const Index i, const Index j, const Index nRow, const Index nCol); BlockTemplate(BlockTemplate &b); BlockTemplate(BlockTemplate &&b); // destructor ~BlockTemplate(void) = default; // access S & getSample(void); const S & getSample(void) const; Index getStartRow(void) const; Index getStartCol(void) const; Index getNRow(void) const; Index getNCol(void) const; // assignement operators BlockTemplate & operator=(const S &sample); BlockTemplate & operator=(const S &&sample); private: S &sample_; const Index i_, j_, nRow_, nCol_; }; // block types typedef BlockTemplate>> Block; typedef const BlockTemplate>> ConstBlock; public: // constructors MatSample(void) = default; MatSample(const Index nSample); MatSample(const Index nSample, const Index nRow, const Index nCol); MatSample(ConstBlock &sampleBlock); MatSample(ConstBlock &&sampleBlock); EIGEN_EXPR_CTOR(MatSample, MatSample, Sample>, ArrayExpr) // destructor virtual ~MatSample(void) = default; // assignement operator MatSample & operator=(Block &sampleBlock); MatSample & operator=(Block &&sampleBlock); MatSample & operator=(ConstBlock &sampleBlock); MatSample & operator=(ConstBlock &&sampleBlock); // product/division by scalar operators (not provided by Eigen) static inline Mat scalarMul(const Mat &m, const T &x) { return m*x; } static inline Mat scalarDiv(const Mat &m, const T &x) { return m/x; } MatSample & operator*=(const T &x); MatSample & operator*=(const T &&x); MatSample & operator/=(const T &x); MatSample & operator/=(const T &&x); // block access ConstBlock block(const Index i, const Index j, const Index nRow, const Index nCol) const; Block block(const Index i, const Index j, const Index nRow, const Index nCol); // resize all matrices void resizeMat(const Index nRow, const Index nCol); // IO type virtual IoType getType(void) const; }; // non-member operators template inline auto operator*(MatSample s, const T &x) ->decltype(SCAL_OP_RETURN(Mul, s, x)) { return SCAL_OP_RETURN(Mul, s, x); } template inline auto operator*(MatSample s, const T &&x) ->decltype(SCAL_OP_RETURN(Mul, s, x)) { return SCAL_OP_RETURN(Mul, s, x); } template inline auto operator*(const T &x, MatSample s)->decltype(s*x) { return s*x; } template inline auto operator*(const T &&x, MatSample s)->decltype(s*x) { return s*x; } template inline auto operator/(MatSample s, const T &x) ->decltype(SCAL_OP_RETURN(Div, s, x)) { return SCAL_OP_RETURN(Div, s, x); } template inline auto operator/(MatSample s, const T &&x) ->decltype(SCAL_OP_RETURN(Div, s, x)) { return SCAL_OP_RETURN(Div, s, x); } // type aliases typedef MatSample DMatSample; typedef MatSample> CMatSample; /****************************************************************************** * Block template implementation * ******************************************************************************/ // constructors //////////////////////////////////////////////////////////////// template template MatSample::BlockTemplate::BlockTemplate(S &sample, const Index i, const Index j, const Index nRow, const Index nCol) : sample_(sample) , i_(i) , j_(j) , nRow_(nRow) , nCol_(nCol) {} template template MatSample::BlockTemplate::BlockTemplate(BlockTemplate &b) : sample_(b.getSample()) , i_(b.getStartRow()) , j_(b.getStartCol()) , nRow_(b.getNRow()) , nCol_(b.getNCol()) {} template template MatSample::BlockTemplate::BlockTemplate(BlockTemplate &&b) : BlockTemplate(b) {} // access ////////////////////////////////////////////////////////////////////// template template S & MatSample::BlockTemplate::getSample(void) { return sample_; } template template const S & MatSample::BlockTemplate::getSample(void) const { return sample_; } template template Index MatSample::BlockTemplate::getStartRow(void) const { return i_; } template template Index MatSample::BlockTemplate::getStartCol(void) const { return j_; } template template Index MatSample::BlockTemplate::getNRow(void) const { return nRow_; } template template Index MatSample::BlockTemplate::getNCol(void) const { return nCol_; } // assignement operators /////////////////////////////////////////////////////// template template MatSample::BlockTemplate & MatSample::BlockTemplate::operator=(const S &sample) { FOR_STAT_ARRAY(sample_, s) { sample_[s].block(i_, j_, nRow_, nCol_) = sample[s]; } return *this; } template template MatSample::BlockTemplate & MatSample::BlockTemplate::operator=(const S &&sample) { *this = sample; return *this; } /****************************************************************************** * DMatSample implementation * ******************************************************************************/ // constructors //////////////////////////////////////////////////////////////// template MatSample::MatSample(const Index nSample) : Sample>(nSample) {} template MatSample::MatSample(const Index nSample, const Index nRow, const Index nCol) : MatSample(nSample) { resizeMat(nRow, nCol); } template MatSample::MatSample(ConstBlock &sampleBlock) : MatSample(sampleBlock.getSample().size(), sampleBlock.getNRow(), sampleBlock.getNCol()) { const MatSample &sample = sampleBlock.getSample(); this->resize(sample.size()); FOR_STAT_ARRAY(*this, s) { (*this)[s] = sample[s].block(sampleBlock.getStartRow(), sampleBlock.getStartCol(), sampleBlock.getNRow(), sampleBlock.getNCol()); } } template MatSample::MatSample(ConstBlock &&sampleBlock) : MatSample(sampleBlock) {} // assignement operator //////////////////////////////////////////////////////// template MatSample & MatSample::operator=(Block &sampleBlock) { MatSample tmp(sampleBlock); this->swap(tmp); return *this; } template MatSample & MatSample::operator=(Block &&sampleBlock) { *this = sampleBlock; return *this; } template MatSample & MatSample::operator=(ConstBlock &sampleBlock) { MatSample tmp(sampleBlock); this->swap(tmp); return *this; } template MatSample & MatSample::operator=(ConstBlock &&sampleBlock) { *this = sampleBlock; return *this; } // product/division by scalar operators (not provided by Eigen) //////////////// template MatSample & MatSample::operator*=(const T &x) { return *this = (*this)*x; } template MatSample & MatSample::operator*=(const T &&x) { return *this = (*this)*x; } template MatSample & MatSample::operator/=(const T &x) { return *this = (*this)/x; } template MatSample & MatSample::operator/=(const T &&x) { return *this = (*this)/x; } // block access //////////////////////////////////////////////////////////////// template typename MatSample::ConstBlock MatSample::block(const Index i, const Index j, const Index nRow, const Index nCol) const { return ConstBlock(*this, i, j, nRow, nCol); } template typename MatSample::Block MatSample::block(const Index i, const Index j, const Index nRow, const Index nCol) { return Block(*this, i, j, nRow, nCol); } // resize all matrices ///////////////////////////////////////////////////////// template void MatSample::resizeMat(const Index nRow, const Index nCol) { FOR_STAT_ARRAY(*this, s) { (*this)[s].resize(nRow, nCol); } } // IO type ///////////////////////////////////////////////////////////////////// template IoObject::IoType MatSample::getType(void) const { return IoType::noType; } END_LATAN_NAMESPACE #endif // Latan_MatSample_hpp_