/** @file Vector.tcc * This is an internal header file, included by other library headers. * You should not attempt to use it directly. */ #ifndef TNet_Vector_tcc #define TNet_Vector_tcc #include #include #include #include #include #include "Common.h" #ifdef HAVE_ATLAS extern "C"{ #include } #endif #include "Common.h" #include "MathAux.h" #include "Matrix.h" namespace TNet { //****************************************************************************** //****************************************************************************** template inline Vector<_ElemT>& Vector<_ElemT>:: Init(const size_t length, bool clear) { if(mpData != NULL) Destroy(); if(length==0){ mpData=NULL; #ifdef STK_MEMALIGN_MANUAL mpFreeData=NULL; #endif mDim=0; return *this; } size_t size; void* data; void* free_data; size = align<16>(length * sizeof(_ElemT)); if (NULL != (data = stk_memalign(16, size, &free_data))) { mpData = static_cast<_ElemT*> (data); #ifdef STK_MEMALIGN_MANUAL mpFreeData = static_cast<_ElemT*> (free_data); #endif mDim = length; } else { throw std::bad_alloc(); } if(clear) Zero(); return *this; } //****************************************************************************** //****************************************************************************** /// Copy data from another vector template inline Vector<_ElemT>& Vector<_ElemT>:: Copy(const Vector<_ElemT>& rV) { assert(Dim() == rV.Dim()); Copy(rV.mpData); return *this; } /// Load data into the vector template Vector<_ElemT>& Vector<_ElemT>:: Copy(const _ElemT* ppData) { std::memcpy(this->mpData, ppData, Dim() * sizeof(_ElemT)); return *this; } template template Vector<_ElemT>& Vector<_ElemT>:: Copy(const Vector<_ElemU> &other){ assert(Dim()==other.Dim()); size_t D=Dim(); for(size_t d=0;d Vector<_ElemT>& Vector<_ElemT>:: CopyVectorizedMatrixRows(const Matrix<_ElemT> &rM) { // TraceLog("Dim = "+to_string(Dim())+", Rows = "+to_string(rM.Rows())+", Cols = "+to_string(rM.Cols())); assert(Dim() == rM.Cols()*rM.Rows()); size_t nCols = rM.Cols(); for(size_t r=0; r Vector<_ElemT>& Vector<_ElemT>:: RemoveElement(size_t i) { assert(i < mDim && "Access out of vector"); for(size_t j = i + 1; j < mDim; j++) this->mpData[j - 1] = this->mpData[j]; mDim--; return *this; } //**************************************************************************** //**************************************************************************** // The destructor template inline void Vector<_ElemT>:: Destroy() { // we need to free the data block if it was defined #ifndef STK_MEMALIGN_MANUAL if (NULL != mpData) free(mpData); #else if (NULL != mpData) free(mpFreeData); mpFreeData = NULL; #endif mpData = NULL; mDim = 0; } //**************************************************************************** //**************************************************************************** template inline void Vector<_ElemT>:: Zero() { std::memset(mpData, 0, mDim * sizeof(_ElemT)); } //**************************************************************************** //**************************************************************************** template inline void Vector<_ElemT>:: Set(_ElemT f) { for(size_t i=0;i Vector<_ElemT>& Vector<_ElemT>:: MatrixRowStack(const Matrix<_ElemT>& rMa) { assert(mDim == rMa.Cols() * rMa.Rows()); _ElemT* inc_data = mpData; const size_t cols = rMa.Cols(); for (size_t i = 0; i < rMa.Rows(); i++) { // copy the data to the propper position memcpy(inc_data, rMa[i], cols * sizeof(_ElemT)); // set new copy position inc_data += cols; } } //**************************************************************************** //**************************************************************************** template Vector<_ElemT>& Vector<_ElemT>:: Row(const Matrix<_ElemT> &rMa, size_t row) { assert(row < rMa.Rows()); const _ElemT *mRow = rMa.pRowData(row); // if(mDim != rMa.Cols()) Init(rMa.Cols()); // automatically resize. memcpy(mpData, mRow, sizeof(_ElemT)*mDim); return *this; } //**************************************************************************** //**************************************************************************** template Vector<_ElemT>& Vector<_ElemT>:: Power(_ElemT power) // takes elements to a power. Throws exception if could not. { for(size_t i=0;i _ElemT Vector<_ElemT>:: Max() const { if(Dim()==0) throw std::runtime_error("Error in Vector::Max(), empty vector\n"); _ElemT ans = (*this)(0); for(size_t i=1;i _ElemT Vector<_ElemT>:: Min() const { if(Dim()==0) throw std::runtime_error("Error in Vector::Min(), empty vector\n"); _ElemT ans = (*this)(0); for(size_t i=1;i Vector<_ElemT>& Vector<_ElemT>:: Col(const Matrix<_ElemT> &rMa, size_t col) { assert(col < rMa.Cols()); // if(mDim != rMa.Cols()) Init(rMa.Cols()); // automatically resize. for(size_t i=0;i _ElemT Vector<_ElemT>:: Sum() const { //note the double accumulator double sum = 0.0; for (size_t i = 0; i < mDim; ++i) { sum += mpData[i]; } return (_ElemT)sum; } //**************************************************************************** //**************************************************************************** template Vector<_ElemT>& Vector<_ElemT>:: AddColSum(const Matrix<_ElemT>& rM) { // note the double accumulator double sum; assert(mDim == rM.Cols()); for (size_t i = 0; i < mDim; ++i) { sum = 0.0; for (size_t j = 0; j < rM.Rows(); ++j) { sum += rM[j][i]; } mpData[i] += sum; } return *this; } //**************************************************************************** //**************************************************************************** template Vector<_ElemT>& Vector<_ElemT>:: AddRowSum(const Matrix<_ElemT>& rM) { // note the double accumulator double sum; assert(mDim == rM.Rows()); for (size_t i = 0; i < mDim; ++i) { sum = 0.0; for (size_t j = 0; j < rM.Cols(); ++j) { sum += rM[i][j]; } mpData[i] += sum; } return *this; } //**************************************************************************** //**************************************************************************** template _ElemT Vector<_ElemT>:: LogSumExp() const { double sum = LOG_0; for (size_t i = 0; i < mDim; ++i) { sum = LogAdd(sum, mpData[i]); } return sum; } //**************************************************************************** //**************************************************************************** template Vector<_ElemT>& Vector<_ElemT>:: Invert() { for (size_t i = 0; i < mDim; ++i) { mpData[i] = static_cast<_ElemT>(1 / mpData[i]); } return *this; } //**************************************************************************** //**************************************************************************** template Vector<_ElemT>& Vector<_ElemT>:: ApplyLog() { for (size_t i = 0; i < mDim; ++i) { mpData[i] = _LOG(mpData[i]); } return *this; } //**************************************************************************** //**************************************************************************** template Vector<_ElemT>& Vector<_ElemT>:: ApplyLog(const Vector<_ElemT>& rV) { assert(mDim==rV.Dim()); for (size_t i = 0; i < mDim; ++i) { mpData[i] = log(rV[i]); } return *this; } //**************************************************************************** //**************************************************************************** template Vector<_ElemT>& Vector<_ElemT>:: ApplyExp() { for (size_t i = 0; i < mDim; ++i) { mpData[i] = _EXP(mpData[i]); } return *this; } //**************************************************************************** //**************************************************************************** template Vector<_ElemT>& Vector<_ElemT>:: ApplySoftMax() { _ElemT lse = LogSumExp(); for (size_t i = 0; i < mDim; ++i) { mpData[i] = exp(mpData[i] - lse); } return *this; } //**************************************************************************** //**************************************************************************** template Vector<_ElemT>& Vector<_ElemT>:: Add(_ElemT c) { for(size_t i = 0; i < mDim; i++) { mpData[i] += c; } return *this; } //**************************************************************************** //**************************************************************************** template Vector<_ElemT>& Vector<_ElemT>:: Subtract(_ElemT c) { for(size_t i = 0; i < mDim; i++) { mpData[i] -= c; } return *this; } //**************************************************************************** //**************************************************************************** template Vector<_ElemT>& Vector<_ElemT>:: Scale(_ElemT c) { for(size_t i = 0; i < mDim; i++) { mpData[i] *= c; } return *this; } //**************************************************************************** //**************************************************************************** template Vector<_ElemT>& Vector<_ElemT>:: MultiplyElements(const Vector<_ElemT>& rV) { assert(mDim == rV.Dim()); for(size_t i = 0; i < mDim; i++) { mpData[i] *= rV[i]; } return *this; } //**************************************************************************** //**************************************************************************** template Vector<_ElemT>& Vector<_ElemT>:: MultiplyElements(_ElemT alpha, const Vector<_ElemT>& rV, const Vector<_ElemT>& rR, _ElemT beta) { assert((mDim == rV.Dim() && mDim == rR.Dim())); for(size_t i = 0; i < mDim; i++) { mpData[i] = alpha * rV[i] * rR[i] + beta * mpData[i]; } return *this; } //**************************************************************************** //**************************************************************************** template Vector<_ElemT>& Vector<_ElemT>:: DivideElements(const Vector<_ElemT>& rV) { assert(mDim == rV.Dim()); for(size_t i = 0; i < mDim; i++) { mpData[i] /= rV[i]; } return *this; } //**************************************************************************** //**************************************************************************** template Vector<_ElemT>& Vector<_ElemT>:: DivideElements(_ElemT alpha, const Vector<_ElemT>& rV, const Vector<_ElemT>& rR, _ElemT beta) { assert((mDim == rV.Dim() && mDim == rR.Dim())); for(size_t i = 0; i < mDim; i++) { mpData[i] = alpha * rV[i]/rR[i] + beta * mpData[i] ; } return *this; } //**************************************************************************** //**************************************************************************** template void Load(std::istream& rIn, Vector<_ElemT>& rV) { std::streamoff pos = rIn.tellg(); if(MatrixVectorIostreamControl::Flags(rIn, ACCUMULATE_INPUT)) { for (size_t i = 0; i < rV.Dim(); i++) { _ElemT tmp; rIn >> tmp; rV[i] += tmp; } } else { for (size_t i = 0; i < rV.Dim(); i++) { rIn >> rV[i]; } } if(rIn.fail()) { throw std::runtime_error("Failed to read vector from stream. File position is "+to_string(pos)); } } template std::istream & operator >> (std::istream& rIn, Vector<_ElemT>& rV) { rIn >> std::ws; if(rIn.peek() == 'v'){ // "new" format: v 1.0 0.2 4.3 ... rIn.get(); long long int tmp=-1; rIn >> tmp; if(rIn.fail() || tmp<0) { throw std::runtime_error("Failed to read vector from stream: no size"); } size_t tmp2 = size_t(tmp); assert((long long int)tmp2 == tmp); if(rV.Dim() != tmp2) rV.Init(tmp2); } Load(rIn,rV); return rIn; } //**************************************************************************** //**************************************************************************** template void Save (std::ostream& rOut, const Vector<_ElemT>& rV) { for (size_t i = 0; i < rV.Dim(); i++) { rOut << rV[i] << ' '; } if(rOut.fail()) { throw std::runtime_error("Failed to write vector to stream"); } } //**************************************************************************** //**************************************************************************** template std::ostream & operator << (std::ostream& rOut, const Vector<_ElemT>& rV) { rOut << "v " << rV.Dim() << " "; Save(rOut,rV); return rOut; } //**************************************************************************** //**************************************************************************** #ifdef HAVE_ATLAS template<> float BlasDot<>(const Vector& rA, const Vector& rB); template<> double BlasDot<>(const Vector& rA, const Vector& rB); template inline Vector<_ElemT>& Vector<_ElemT>:: DotMul(const Vector<_ElemT> &rV){ assert(mDim == rV.mDim); const _ElemT *other_data = rV.pData(); _ElemT *my_data = mpData, *my_data_end = my_data+mDim; for(;my_data Vector& Vector:: BlasAxpy(const float alpha, const Vector& rV); template<> Vector& Vector:: BlasAxpy(const double alpha, const Vector& rV); template<> Vector& Vector:: BlasGemv(const float alpha, const Matrix& rM, MatrixTrasposeType trans, const Vector& rV, const float beta); template<> Vector& Vector:: BlasGemv(const double alpha, const Matrix& rM, MatrixTrasposeType trans, const Vector& rV, const double beta); #else #error Routines in this section are not implemented yet without BLAS #endif template _ElemT InnerProduct(const Vector<_ElemT> &v1, const Matrix<_ElemT> &M, const Vector<_ElemT> &v2){ assert(v1.size()==M.Rows() && v2.size()==M.Cols()); Vector<_ElemT> vtmp(M.Rows()); vtmp.BlasGemv(1.0, M, NO_TRANS, v2, 0.0); return BlasDot(v1, vtmp); } } // namespace TNet #endif // TNet_Vector_tcc