Files
mlpack/fastlib/u/nvasil/sparse_matrix/sparse_vector.h
T
vasiloglou ad86872105 added more functionality
I have to fix some errors for eigenvalues
2007-12-20 02:57:48 +00:00

284 lines
8.0 KiB
C++

/*
* =====================================================================================
*
* Filename: sparse_vector.h
*
* Description:
*
* Version: 1.0
* Created: 12/03/2007 12:44:34 AM EST
* Revision: none
* Compiler: gcc
*
* Author: Nikolaos Vasiloglou (NV), nvasil@ieee.org
* Company: Georgia Tech Fastlab-ESP Lab
*
* =====================================================================================
*/
#ifndef SPARSE_VECTOR_H_
#define SPARSE_VECTOR_H_
#ifndef HAVE_CONFIG_H
#define HAVE_CONFIG_H
#endif
#include <string>
#include <map>
#include <vector>
#include <algorithm>
#include "fastlib/fastlib.h"
#include "la/matrix.h"
#include "Epetra_CrsMatrix.h"
#include "Epetra_SerialComm.h"
#include "Epetra_Map.h"
class SparseVectorTest;
class Sparsev;
class SparseVector {
public:
friend class SparseVectorTest;
friend class Sparsev;
SparseVector() {
map_=NULL;
}
SparseVector(std::vector<index_t> &indices,
Vector &values,
index_t dimension);
SparseVector(std::map<index_t, double> &data,
index_t dimension);
SparseVector(index_t estimated_non_zero_elements,
index_t dimension);
SparseVector(Epetra_CrsMatrix *one_dim_matrix,
index_t dimension);
void Destruct();
SparseVector(const SparseVector &other);
~SparseVector() {
Destruct();
}
void Init(index_t dimension);
void Init(std::vector<index_t> &indices, Vector &values,
index_t dimension);
void Init(std::vector<index_t> &indices, std::vector<double> &values,
index_t dimension);
void Init(index_t *indices, double *values, index_t len, index_t dimension);
void Init(std::map<index_t, double> &data, index_t dimension);
void Init(index_t estimated_non_zero_elements, index_t dimension);
void Init(Epetra_CrsMatrix *one_dim_matrix, index_t dimension);
void Copy(const SparseVector &other);
void MakeSubvector(index_t start_index,
index_t len,
SparseVector* dest);
double get(index_t i);
void set(index_t i, double value);
void set_start(index_t i);
void set_end(index_t i);
void Lock();
private:
Epetra_CrsMatrix *vector_;
Epetra_SerialComm comm_;
Epetra_Map *map_;
index_t *my_global_elements_;
index_t dimension_;
index_t start_;
index_t end_;
bool own_;
};
class Sparsev {
public:
static inline void AddVectors(SparseVector &v1, SparseVector &v2, SparseVector* sum) {
if (unlikely(v1.dimension_ != v2.dimension_)) {
FATAL("Sparse Vectors have different dimensions %i != %i", v1.dimension_, v2.dimension_);
}
index_t num1, num2;
double *values1, *values2;
index_t *indices1, *indices2;
v1.vector_->ExtractGlobalRowView(0, num1, values1, indices1);
v2.vector_->ExtractGlobalRowView(0, num2, values2, indices2);
std::vector<double> values3;
std::vector<index_t> indices3;
index_t i=0;
index_t j=0;
while (likely(i<num1 && j<num2)) {
while (indices1[i] < indices2[j]) {
values3.push_back(values1[i]);
indices3.push_back(indices1[i]);
i++;
if unlikely((i>=num1)) {
break;
}
}
if ( likely(i<num1) && indices1[i] == indices2[j]) {
values3.push_back(values1[i] + values2[j]);
indices3.push_back(indices1[i]);
} else {
values3.push_back(values2[j]);
indices3.push_back(indices2[j]);
}
j++;
}
if (i<num1) {
values3.insert(values3.end(), values1+i, values1+num1);
indices3.insert(indices3.end(), indices1+i, indices1+num1);
}
if (j<num2) {
values3.insert(values3.end(), values2+j, values2+num2);
indices3.insert(indices3.end(), indices2+i, indices2+num2);
}
sum->Init(indices3, values3, v1.dimension_);
}
static inline void SubtractVectors(SparseVector &v1, SparseVector &v2, SparseVector *diff) {
if (unlikely(v1.dimension_ != v2.dimension_)) {
FATAL("Sparse Vectors have different dimensions %i != %i", v1.dimension_, v2.dimension_);
}
index_t num1, num2;
double *values1, *values2;
index_t *indices1, *indices2;
v1.vector_->ExtractGlobalRowView(0, num1, values1, indices1);
v2.vector_->ExtractGlobalRowView(0, num2, values2, indices2);
std::vector<double> values3;
std::vector<index_t> indices3;
index_t i=0;
index_t j=0;
while (likely(i<num1 && j<num2)) {
while (indices1[i] < indices2[j]) {
values3.push_back(values1[i]);
indices3.push_back(indices1[i]);
i++;
if unlikely((i>=num1)) {
break;
}
}
if ( likely(i<num1) && indices1[i] == indices2[j]) {
values3.push_back(values1[i] - values2[j]);
indices3.push_back(indices1[i]);
} else {
values3.push_back(-values2[j]);
indices3.push_back(indices2[j]);
}
j++;
}
if (i<num1) {
values3.insert(values3.end(), values1+i, values1+num1);
indices3.insert(indices3.end(), indices1+i, indices1+num1);
}
if (j<num2) {
for(index_t jj=i; jj<num2; jj++) {
values3.push_back(-values2[jj]);
indices3.push_back(indices2[jj]);
}
}
diff->Init(indices3, values3, v1.dimension_);
}
static inline void PointProductVectors(SparseVector &v1, SparseVector &v2, SparseVector *point_prod) {
if (unlikely(v1.dimension_ != v2.dimension_)) {
FATAL("Sparse Vectors have different dimensions %i != %i", v1.dimension_, v2.dimension_);
}
index_t num1, num2;
double *values1, *values2;
index_t *indices1, *indices2;
v1.vector_->ExtractGlobalRowView(0, num1, values1, indices1);
v2.vector_->ExtractGlobalRowView(0, num2, values2, indices2);
std::vector<double> values3;
std::vector<index_t> indices3;
index_t i=0;
index_t j=0;
while (likely(i<num1 && j<num2)) {
while (indices1[i] < indices2[j]) {
i++;
if unlikely((i>=num1)) {
break;
}
}
if ( likely(i<num1) && indices1[i] == indices2[j]) {
values3.push_back(values1[i] * values2[j]);
indices3.push_back(indices1[i]);
}
j++;
}
point_prod->Init(indices3, values3, v1.dimension_);
}
static inline void DotProductVectors(SparseVector &v1, SparseVector &v2, double *dot_product) {
if (unlikely(v1.dimension_ != v2.dimension_)) {
FATAL("Sparse Vectors have different dimensions %i != %i", v1.dimension_, v2.dimension_);
}
index_t num1, num2;
double *values1, *values2;
index_t *indices1, *indices2;
v1.vector_->ExtractGlobalRowView(0, num1, values1, indices1);
v2.vector_->ExtractGlobalRowView(0, num2, values2, indices2);
index_t i=0;
index_t j=0;
*dot_product=0;
while (likely(i<num1 && j<num2)) {
while (indices1[i] < indices2[j]) {
i++;
if unlikely((i>=num1)) {
break;
}
}
if ( likely(i<num1) && indices1[i] == indices2[j]) {
*dot_product += values1[i] * values2[j];
}
j++;
}
}
static inline void DistanceSqEuclideanVector(SparseVector &v1,
SparseVector &v2,
double *dist) {
if (unlikely(v1.dimension_ != v2.dimension_)) {
FATAL("Sparse Vectors have different dimensions %i != %i", v1.dimension_, v2.dimension_);
}
index_t num1, num2;
double *values1, *values2;
index_t *indices1, *indices2;
v1.vector_->ExtractGlobalRowView(0, num1, values1, indices1);
v2.vector_->ExtractGlobalRowView(0, num2, values2, indices2);
std::vector<double> values3;
std::vector<index_t> indices3;
index_t i=0;
index_t j=0;
*dist=0;
while (likely(i<num1 && j<num2)) {
while (indices1[i] < indices2[j]) {
values3.push_back(values1[i]);
indices3.push_back(indices1[i]);
i++;
if unlikely((i>=num1)) {
break;
}
}
if ( likely(i<num1) && indices1[i] == indices2[j]) {
*dist += (values1[i] - values2[j]) * (values1[i] - values2[j]);
} else {
*dist += values2[j] * values2[j];
}
j++;
}
if (i<num1) {
for(index_t ii=i+1; ii<num1; ii++) {
*dist += values1[ii] * values1[ii];
}
}
if (j<num2) {
for(index_t jj=j; jj<num2; jj++) {
*dist += values2[jj] * values2[jj];
}
}
}
template<int t_pow>
inline void RawLMetricVectors(SparseVector &v1, SparseVector &v2, double *dist);
};
#include "sparse_vector_impl.h"
#endif