/*! * \file * \brief Sparse Vector Class definitions * \author Tony Ottosson and Tobias Ringstrom * * ------------------------------------------------------------------------- * * IT++ - C++ library of mathematical, signal processing, speech processing, * and communications classes and functions * * Copyright (C) 1995-2007 (see AUTHORS file for a list of contributors) * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * ------------------------------------------------------------------------- */ #ifndef SVEC_H #define SVEC_H #ifndef _MSC_VER # include #else # include #endif #include #include #include namespace itpp { // Declaration of class Vec template class Vec; // Declaration of class Sparse_Vec template class Sparse_Vec; // ----------------------- Sparse_Vec Friends ------------------------------- //! v1+v2 where v1 and v2 are sparse vector template Sparse_Vec operator+(const Sparse_Vec &v1, const Sparse_Vec &v2); //! v1*v2 where v1 and v2 are sparse vectors template T operator*(const Sparse_Vec &v1, const Sparse_Vec &v2); //! v1*v2 where v1 is a sparse vector and v2 is a dense vector template T operator*(const Sparse_Vec &v1, const Vec &v2); //! v1*v2 where v1 is a dense vector and v2 is a sparse vector template T operator*(const Vec &v1, const Sparse_Vec &v2); //! Elementwise multiplication of two sparse vectors returning a sparse vector template Sparse_Vec elem_mult(const Sparse_Vec &v1, const Sparse_Vec &v2); //! Elementwise multiplication of a sparse vector and a dense vector returning a dense vector template Vec elem_mult(const Sparse_Vec &v1, const Vec &v2); //! Elementwise multiplication of a sparse vector and a dense vector returning a sparse vector template Sparse_Vec elem_mult_s(const Sparse_Vec &v1, const Vec &v2); //! Elementwise multiplication of a dense vector and a sparse vector returning a dense vector template Vec elem_mult(const Vec &v1, const Sparse_Vec &v2); //! Elementwise multiplication of a dense vector and a sparse vector returning a sparse vector template Sparse_Vec elem_mult_s(const Vec &v1, const Sparse_Vec &v2); /*! \brief Templated sparse vector class \author Tony Ottosson and Tobias Ringstrom A sparse vector is a vector where most elements are zero. The maximum number of none-zero elements is a parameter to the constructor. The elements are stored in random order, i.e. they are not sorted. */ template class Sparse_Vec { public: //! Default constructor Sparse_Vec(); /*! \brief Initiate an empty sparse vector \param sz Size of the sparse vector (i.e. maximum index is (\c sz - 1)) \param data_init Maximum number of non-zero elements in the sparse vector (default value 200) */ Sparse_Vec(int sz, int data_init=200); /*! \brief Initiate a new sparse vector. \param v The elements of \c v are copied into the new sparse vector */ Sparse_Vec(const Sparse_Vec &v); /*! \brief Initiate a new sparse vector from a dense vector. \param v The elements of \c v are copied into the new sparse vector */ Sparse_Vec(const Vec &v); /*! \brief Initiate a new sparse vector from a dense vector. Elements of \c v larger than \c epsilon are copied into the new sparse vector. \note If the type T is complex, then the elements of \c v larger than \c abs(epsilon) are copied into the new sparse vector. */ Sparse_Vec(const Vec &v, T epsilon); //! Destructor ~Sparse_Vec(); /*! \brief Set the size \c sz of the sparse vector. Default value \c data_init=-1 \c => allocated size for the data is not changed. \param sz Size of the sparse vector (i.e. maximum index is (\c sz - 1)) \param data_init Maximum number of non-zero elements in the sparse vector (default value -1 \c => allocated size for the data is not changed) */ void set_size(int sz, int data_init=-1); //! Returns the size of the sparse vector int size() const { return v_size; } //! Number of non-zero elements in the sparse vector inline int nnz() { if (check_small_elems_flag) { remove_small_elements(); } return used_size; } //! Returns the density of the sparse vector: (number of non-zero elements)/(size of the vector) double density(); //! Set that all elements smaller than \a epsilon should be set to zero. void set_small_element(const T& epsilon); /*! Removes all elements that are smaller than \a epsilon from the non-zero elements. \note The small element \a epsilon can be set by the member function set_small_element. If no small value is set, the default value is always \c epsilon=0. */ void remove_small_elements(); /*! \brief Set the maximum number of non-zero elements to \c new_size \param new_size The new maximum number of non-zero elements. */ void resize_data(int new_size); //! Set the maximum number of non-zero elements equal to the actual number of non-zero elements void compact(); //! Returns a full, dense vector in \c v void full(Vec &v) const; //! Returns a full, dense vector Vec full() const; //! Returns the element with index \c i T operator()(int i) const; //! Set element \c i equal to \c v void set(int i, T v); //! Set the elements of the sparse vector with indices \c index_vec to the values in \c v void set(const ivec &index_vec, const Vec &v); //! Set a new element with index \c i equal to \c v void set_new(int i, T v); //! Set new elements with indices \c index_vec equal to the values in \c v (no check whether the same index is used several times) void set_new(const ivec &index_vec, const Vec &v); //! Add element \c i with \c v void add_elem(const int i, const T v); //! Add \c v to the elements specified by \c index_vec with \c v void add(const ivec &index_vec, const Vec &v); //! Set the sparse vector to the all zero vector (removes all non-zero elements) void zeros(); //! Set the i-th element to zero (i.e. clear that element if it contains a non-zero value) void zero_elem(const int i); //! Clear all non-zero elements of the sparse vector void clear(); //! Clear the i-th element (if it contains a non-zero value) void clear_elem(const int i); /*! \brief Extract the reference to the p-th non-zero data element */ inline void get_nz_data(int p, T& data_out) { if (check_small_elems_flag) { remove_small_elements(); } data_out = data[p]; } //! Returns the p-th non-zero data element inline T get_nz_data(int p) { if (check_small_elems_flag) { remove_small_elements(); } return data[p]; } //! Returns the vector index of the p-th non-zero element inline int get_nz_index(int p) { if (check_small_elems_flag) { remove_small_elements(); } return index[p]; } //! Returns the p-th non-zero value in \c dat and the corresponding vector index in \c idx inline void get_nz(int p, int &idx, T &dat) { if (check_small_elems_flag) { remove_small_elements(); } idx=index[p]; dat=data[p]; } //! Retrun the indices of non-zero values ivec get_nz_indices(); //! Return sparse subvector from index \c i1 to index \c i2 Sparse_Vec get_subvector(int i1, int i2) const; //! Returns the sum of all values squared T sqr() const; //! Assign sparse vector the value and length of the sparse vector \c v void operator=(const Sparse_Vec &v); //! Assign sparse vector the value and length of the dense vector \c v void operator=(const Vec &v); //! Returns the sign inverse of all elements in the sparse vector Sparse_Vec operator-() const; //! Compare two sparse vectors. False if wrong sizes or different values bool operator==(const Sparse_Vec &v); //! Add sparse vector \c v to all non-zero elements of the sparse vector void operator+=(const Sparse_Vec &v); //! Add vector \c v to all non-zero elements of the sparse vector void operator+=(const Vec &v); //! Subtract sparse vector \c v from all non-zero elements of the sparse vector void operator-=(const Sparse_Vec &v); //! Subtract vector \c v from all non-zero elements of the sparse vector void operator-=(const Vec &v); //! Multiply the scalar \c v to all non-zero elements of the sparse vector void operator*=(const T &v); //! Divide all non-zero elements of the sparse vector with the scalar \c v void operator/=(const T &v); //! Addition v1+v2 where v1 and v2 are sparse vector friend Sparse_Vec operator+<>(const Sparse_Vec &v1, const Sparse_Vec &v2); //! Scalar product v1*v2 where v1 and v2 are sparse vectors friend T operator*<>(const Sparse_Vec &v1, const Sparse_Vec &v2); //! Scalar product v1*v2 where v1 is a sparse vector and v2 is a dense vector friend T operator*<>(const Sparse_Vec &v1, const Vec &v2); //! Scalar product v1*v2 where v1 is a dense vector and v2 is a sparse vector friend T operator*<>(const Vec &v1, const Sparse_Vec &v2); //! Element wise multiplication of two sparse vectors friend Sparse_Vec elem_mult <>(const Sparse_Vec &v1, const Sparse_Vec &v2); //! Element wise multiplication of a sparse vector and a dense vector friend Vec elem_mult <>(const Sparse_Vec &v1, const Vec &v2); //! Element wise multiplication of a sparse vector and a dense vector returning a sparse vector friend Sparse_Vec elem_mult_s <>(const Sparse_Vec &v1, const Vec &v2); //! Element wise multiplication of a a dense vector and a sparse vector friend Vec elem_mult <>(const Vec &v1, const Sparse_Vec &v2); //! Element wise multiplication of a a dense vector and a sparse vector returning a sparse vector friend Sparse_Vec elem_mult_s <>(const Vec &v1, const Sparse_Vec &v2); private: void init(); void alloc(); void free(); int v_size, used_size, data_size; T *data; int *index; T eps; bool check_small_elems_flag; }; /*! \relates Sparse_Vec \brief Type definition of an integer sparse vector */ typedef Sparse_Vec sparse_ivec; /*! \relates Sparse_Vec \brief Type definition of a double sparse vector */ typedef Sparse_Vec sparse_vec; /*! \relates Sparse_Vec \brief Type definition of a complex sparse vector */ typedef Sparse_Vec > sparse_cvec; // ----------------------- Implementation starts here -------------------------------- template void Sparse_Vec::init() { v_size = 0; used_size = 0; data_size = 0; data = 0; index = 0; eps = 0; check_small_elems_flag = true; } template void Sparse_Vec::alloc() { if (data_size != 0) { data = new T[data_size]; index = new int[data_size]; } } template void Sparse_Vec::free() { delete [] data; data = 0; delete [] index; index = 0; } template Sparse_Vec::Sparse_Vec() { init(); } template Sparse_Vec::Sparse_Vec(int sz, int data_init) { init(); v_size = sz; used_size = 0; data_size = data_init; alloc(); } template Sparse_Vec::Sparse_Vec(const Sparse_Vec &v) { init(); v_size = v.v_size; used_size = v.used_size; data_size = v.data_size; eps = v.eps; check_small_elems_flag = v.check_small_elems_flag; alloc(); for (int i=0; i Sparse_Vec::Sparse_Vec(const Vec &v) { init(); v_size = v.size(); used_size = 0; data_size = std::min(v.size(), 10000); alloc(); for (int i=0; i Sparse_Vec::Sparse_Vec(const Vec &v, T epsilon) { init(); v_size = v.size(); used_size = 0; data_size = std::min(v.size(), 10000); eps = epsilon; alloc(); double e = std::abs(epsilon); for (int i=0; i e) { if (used_size == data_size) resize_data(data_size*2); data[used_size] = v(i); index[used_size] = i; used_size++; } } compact(); } template Sparse_Vec::~Sparse_Vec() { free(); } template void Sparse_Vec::set_size(int new_size, int data_init) { v_size = new_size; used_size = 0; if (data_init != -1){ free(); data_size = data_init; alloc(); } } template double Sparse_Vec::density() { if (check_small_elems_flag) { remove_small_elements(); } //return static_cast(used_size) / v_size; return double(used_size) / v_size; } template void Sparse_Vec::set_small_element(const T& epsilon) { eps=epsilon; remove_small_elements(); } template void Sparse_Vec::remove_small_elements() { int i; int nrof_removed_elements = 0; double e; //Remove small elements e = std::abs(eps); for (i=0;i 0) { data[i-nrof_removed_elements] = data[i]; index[i-nrof_removed_elements] = index[i]; } } //Set new size after small elements have been removed used_size -= nrof_removed_elements; //Set the flag to indicate that all small elements have been removed check_small_elems_flag = false; } template void Sparse_Vec::resize_data(int new_size) { it_assert(new_size>=used_size, "Sparse_Vec::resize_data(int new_size): New size is to small"); if (new_size != data_size) { if (new_size == 0) free(); else { T *tmp_data = data; int *tmp_pos = index; data_size = new_size; alloc(); for (int p=0; p void Sparse_Vec::compact() { if (check_small_elems_flag) { remove_small_elements(); } resize_data(used_size); } template void Sparse_Vec::full(Vec &v) const { v.set_size(v_size); v = T(0); for (int p=0; p Vec Sparse_Vec::full() const { Vec r(v_size); full(r); return r; } // This is slow. Implement a better search template T Sparse_Vec::operator()(int i) const { it_assert_debug(i >= 0 && i < v_size, "The index of the element is out of range"); bool found = false; int p; for (p=0; p void Sparse_Vec::set(int i, T v) { it_assert_debug(i >= 0 && i < v_size, "The index of the element is out of range"); bool found = false; bool larger_than_eps; int p; for (p=0; p std::abs(eps)); if (found && larger_than_eps) data[p] = v; else if (larger_than_eps) { if (used_size == data_size) resize_data(data_size*2+100); data[used_size] = v; index[used_size] = i; used_size++; } //Check if the stored element is smaller than eps. In that case it should be removed. if (std::abs(v) <= std::abs(eps)) { remove_small_elements(); } } template void Sparse_Vec::set_new(int i, T v) { it_assert_debug(v_size > i, "The index of the element exceeds the size of the sparse vector"); //Check that the new element is larger than eps! if (std::abs(v) > std::abs(eps)) { if (used_size == data_size) resize_data(data_size*2+100); data[used_size] = v; index[used_size] = i; used_size++; } } template void Sparse_Vec::add_elem(const int i, const T v) { bool found = false; int p; it_assert_debug(v_size > i, "The index of the element exceeds the size of the sparse vector"); for (p=0; p void Sparse_Vec::add(const ivec& index_vec, const Vec& v) { bool found = false; int i,p,q; int nrof_nz=v.size(); it_assert_debug(v_size>max(index_vec),"The indices exceeds the size of the sparse vector"); //Elements are added if they have identical indices for (q=0; q void Sparse_Vec::zeros() { used_size = 0; check_small_elems_flag = false; } template void Sparse_Vec::zero_elem(const int i) { bool found = false; int p; it_assert_debug(v_size > i, "The index of the element exceeds the size of the sparse vector"); for (p=0; p void Sparse_Vec::clear() { used_size = 0; check_small_elems_flag = false; } template void Sparse_Vec::clear_elem(const int i) { bool found = false; int p; it_assert_debug(v_size > i, "The index of the element exceeds the size of the sparse vector"); for (p=0; p void Sparse_Vec::set(const ivec& index_vec, const Vec& v) { it_assert_debug(v_size>max(index_vec),"The indices exceeds the size of the sparse vector"); //Clear all old non-zero elements clear(); //Add the new non-zero elements add(index_vec,v); } template void Sparse_Vec::set_new(const ivec& index_vec, const Vec& v) { int q; int nrof_nz=v.size(); it_assert_debug(v_size>max(index_vec),"The indices exceeds the size of the sparse vector"); //Clear all old non-zero elements clear(); for (q=0; q std::abs(eps)) { if (used_size == data_size) resize_data(data_size*2+100); data[used_size] = v(q); index[used_size] = index_vec(q); used_size++; } } } template ivec Sparse_Vec::get_nz_indices() { int n = nnz(); ivec r(n); for (int i = 0; i < n; i++) { r(i) = get_nz_index(i); } return r; } template Sparse_Vec Sparse_Vec::get_subvector(int i1, int i2) const { it_assert_debug(v_size > i1 && v_size > i2 && i1<=i2 && i1>=0, "The index of the element exceeds the size of the sparse vector"); Sparse_Vec r(i2-i1+1); for (int p=0; p= i1 && index[p] <= i2) { if (r.used_size == r.data_size) r.resize_data(r.data_size*2+100); r.data[r.used_size] = data[p]; r.index[r.used_size] = index[p]-i1; r.used_size++; } } r.eps = eps; r.check_small_elems_flag = check_small_elems_flag; r.compact(); return r; } template T Sparse_Vec::sqr() const { T sum(0); for (int p=0; p void Sparse_Vec::operator=(const Sparse_Vec &v) { free(); v_size = v.v_size; used_size = v.used_size; data_size = v.data_size; eps = v.eps; check_small_elems_flag = v.check_small_elems_flag; alloc(); for (int i=0; i void Sparse_Vec::operator=(const Vec &v) { free(); v_size = v.size(); used_size = 0; data_size = std::min(v.size(), 10000); eps = T(0); check_small_elems_flag = false; alloc(); for (int i=0; i Sparse_Vec Sparse_Vec::operator-() const { Sparse_Vec r(v_size, used_size); for (int p=0; p bool Sparse_Vec::operator==(const Sparse_Vec &v) { int p,q; bool found=false; //Remove small elements before comparing the two sparse_vectors if (check_small_elems_flag) remove_small_elements(); if (v_size!=v.v_size) { //Return false if vector sizes are unequal return false; } else { for(p=0;p v.used_size) { //Return false if number of non-zero elements is less in v return false; } else { //Ensure that the remaining non-zero elements in v are smaller than v.eps int nrof_small_elems = 0; for(q=0;q return true return true; } template void Sparse_Vec::operator+=(const Sparse_Vec &v) { int i,p; T tmp_data; int nrof_nz_v=v.used_size; it_assert_debug(v_size == v.size(), "Attempted addition of unequal sized sparse vectors"); for (p=0; p void Sparse_Vec::operator+=(const Vec &v) { int i; it_assert_debug(v_size == v.size(), "Attempted addition of unequal sized sparse vectors"); for (i=0; i void Sparse_Vec::operator-=(const Sparse_Vec &v) { int i,p; T tmp_data; int nrof_nz_v=v.used_size; it_assert_debug(v_size == v.size(), "Attempted subtraction of unequal sized sparse vectors"); for (p=0; p void Sparse_Vec::operator-=(const Vec &v) { int i; it_assert_debug(v_size == v.size(), "Attempted subtraction of unequal sized sparse vectors"); for (i=0; i void Sparse_Vec::operator*=(const T &v) { int p; for (p=0; p void Sparse_Vec::operator/=(const T &v) { int p; for (p=0; p 0) { check_small_elems_flag = true; } } template T operator*(const Sparse_Vec &v1, const Sparse_Vec &v2) { it_assert_debug(v1.v_size == v2.v_size, "Sparse_Vec * Sparse_Vec"); T sum(0); Vec v1f(v1.v_size); v1.full(v1f); for (int p=0; p T operator*(const Sparse_Vec &v1, const Vec &v2) { it_assert_debug(v1.size() == v2.size(), "Multiplication of unequal sized vectors attempted"); T sum(0); for (int p1=0; p1 T operator*(const Vec &v1, const Sparse_Vec &v2) { it_assert_debug(v1.size() == v2.size(), "Multiplication of unequal sized vectors attempted"); T sum(0); for (int p2=0; p2 Sparse_Vec elem_mult(const Sparse_Vec &v1, const Sparse_Vec &v2) { it_assert_debug(v1.v_size == v2.v_size, "elem_mult(Sparse_Vec, Sparse_Vec)"); Sparse_Vec r(v1.v_size); ivec pos(v1.v_size); pos = -1; for (int p1=0; p1 Vec elem_mult(const Sparse_Vec &v1, const Vec &v2) { it_assert_debug(v1.v_size == v2.size(), "elem_mult(Sparse_Vec, Vec)"); Vec r(v1.v_size); r = T(0); for (int p1=0; p1 Sparse_Vec elem_mult_s(const Sparse_Vec &v1, const Vec &v2) { it_assert_debug(v1.v_size == v2.size(), "elem_mult(Sparse_Vec, Vec)"); Sparse_Vec r(v1.v_size); for (int p1=0; p1 Vec elem_mult(const Vec &v1, const Sparse_Vec &v2) { it_assert_debug(v1.size() == v2.v_size, "elem_mult(Vec, Sparse_Vec)"); Vec r(v2.v_size); r = T(0); for (int p2=0; p2 Sparse_Vec elem_mult_s(const Vec &v1, const Sparse_Vec &v2) { it_assert_debug(v1.size() == v2.v_size, "elem_mult(Vec, Sparse_Vec)"); Sparse_Vec r(v2.v_size); for (int p2=0; p2 Sparse_Vec operator+(const Sparse_Vec &v1, const Sparse_Vec &v2) { it_assert_debug(v1.v_size == v2.v_size, "Sparse_Vec + Sparse_Vec"); Sparse_Vec r(v1); ivec pos(v1.v_size); pos = -1; for (int p1=0; p1 inline Sparse_Vec sparse(const Vec &v) { Sparse_Vec s(v); return s; } //! Convert a dense vector \c v into its sparse representation template inline Sparse_Vec sparse(const Vec &v, T epsilon) { Sparse_Vec s(v, epsilon); return s; } //! Convert a sparse vector \c s into its dense representation template inline Vec full(const Sparse_Vec &s) { Vec v; s.full(v); return v; } //! \cond // --------------------------------------------------------------------- // Instantiations // --------------------------------------------------------------------- #ifdef HAVE_EXTERN_TEMPLATE extern template class Sparse_Vec; extern template class Sparse_Vec; extern template class Sparse_Vec >; extern template sparse_ivec operator+(const sparse_ivec &, const sparse_ivec &); extern template sparse_vec operator+(const sparse_vec &, const sparse_vec &); extern template sparse_cvec operator+(const sparse_cvec &, const sparse_cvec &); extern template int operator*(const sparse_ivec &, const sparse_ivec &); extern template double operator*(const sparse_vec &, const sparse_vec &); extern template std::complex operator*(const sparse_cvec &, const sparse_cvec &); extern template int operator*(const sparse_ivec &, const ivec &); extern template double operator*(const sparse_vec &, const vec &); extern template std::complex operator*(const sparse_cvec &, const cvec &); extern template int operator*(const ivec &, const sparse_ivec &); extern template double operator*(const vec &, const sparse_vec &); extern template std::complex operator*(const cvec &, const sparse_cvec &); extern template sparse_ivec elem_mult(const sparse_ivec &, const sparse_ivec &); extern template sparse_vec elem_mult(const sparse_vec &, const sparse_vec &); extern template sparse_cvec elem_mult(const sparse_cvec &, const sparse_cvec &); extern template ivec elem_mult(const sparse_ivec &, const ivec &); extern template vec elem_mult(const sparse_vec &, const vec &); extern template cvec elem_mult(const sparse_cvec &, const cvec &); extern template sparse_ivec elem_mult_s(const sparse_ivec &, const ivec &); extern template sparse_vec elem_mult_s(const sparse_vec &, const vec &); extern template sparse_cvec elem_mult_s(const sparse_cvec &, const cvec &); extern template ivec elem_mult(const ivec &, const sparse_ivec &); extern template vec elem_mult(const vec &, const sparse_vec &); extern template cvec elem_mult(const cvec &, const sparse_cvec &); extern template sparse_ivec elem_mult_s(const ivec &, const sparse_ivec &); extern template sparse_vec elem_mult_s(const vec &, const sparse_vec &); extern template sparse_cvec elem_mult_s(const cvec &, const sparse_cvec &); #endif // HAVE_EXTERN_TEMPLATE //! \endcond } // namespace itpp #endif // #ifndef SVEC_H