📄 nist_spblas.cc
字号:
/*
*
* Sparse BLAS (Basic Linear Algebra Subprograms) Library
*
* A C++ implementation of the routines specified by the ANSI C
* interface specification of the Sparse BLAS in the BLAS Technical
* Forum Standard[1]. For details, see [2].
*
* Mathematical and Computational Sciences Division
* National Institute of Technology,
* Gaithersburg, MD USA
*
*
* [1] BLAS Technical Forum: www.netlib.org/blas/blast-forum/
* [2] I. S. Duff, M. A. Heroux, R. Pozo, "An Overview of the Sparse Basic
* Linear Algebra Subprograms: The new standard of the BLAS Techincal
* Forum," Vol. 28, No. 2, pp. 239-267,ACM Transactions on Mathematical
* Software (TOMS), 2002.
*
*
* DISCLAIMER:
*
* This software was developed at the National Institute of Standards and
* Technology (NIST) by employees of the Federal Government in the course
* of their official duties. Pursuant to title 17 Section 105 of the
* United States Code, this software is not subject to copyright protection
* and is in the public domain. NIST assumes no responsibility whatsoever for
* its use by other parties, and makes no guarantees, expressed or implied,
* about its quality, reliability, or any other characteristic.
*
*
*/
/* numeric is for accumulate() below */
#include <iostream>
#include <complex>
#include <numeric>
#include <vector>
#include <utility>
/* pair defined here */
#include "blas_sparse.h"
#ifdef SPBLAS_ERROR_FATAL
#include <cassert>
#define ASSERT_RETURN(x, ret_val) assert(x)
#define ERROR_RETURN(ret_val) assert(0)
#else
#define ASSERT_RETURN(x, ret_val) {if (!(x)) return ret_val;}
#define ERROR_RETURN(ret_val) return ret_val
#endif
using namespace std;
namespace NIST_SPBLAS
{
/**
Generic sparse matrix (base) class: defines only the structure
(size, symmetry, etc.) and maintains state during construction,
but does not specify the actual nonzero values, or their type.
*/
class Sp_mat
{
private:
int num_rows_;
int num_cols_;
int num_nonzeros_;
/* ... */
int void_;
int nnew_; /* avoid using "new" since it is a C++ keyword */
int open_;
int valid_;
int unit_diag_ ;
int complex_;
int real_;
int single_precision_;
int double_precision_;
int upper_triangular_;
int lower_triangular_;
int upper_symmetric_;
int lower_symmetric_;
int upper_hermitian_;
int lower_hermitian_;
int general_;
int one_base_;
/* optional block information */
int Mb_; /* matrix is partitioned into Mb x Nb blocks */
int Nb_; /* otherwise 0, if regular (non-blocked) matrix */
int k_; /* for constant blocks, each block is k x l */
int l_; /* otherwise 0, if variable blocks are used. */
int rowmajor_; /* 1,if block storage is rowm major. */
int colmajor_; /* 1,if block storage is column major. */
/* unused optimization paramters */
int opt_regular_;
int opt_irregular_;
int opt_block_;
int opt_unassembled_;
vector<int> K_; /* these are GLOBAL index of starting point of block */
vector<int> L_; /* i.e. block(i,j) starts at global location (K[i],L[i]) */
/* and of size (K[i+1]-K[i] x L[i+1]-L[i]) */
public:
Sp_mat(int M, int N) :
num_rows_(M), /* default construction */
num_cols_(N),
num_nonzeros_(0),
void_(0),
nnew_(1),
open_(0),
valid_(0),
unit_diag_(0),
complex_(0),
real_(0),
single_precision_(0),
double_precision_(0),
upper_triangular_(0),
lower_triangular_(0),
upper_symmetric_(0),
lower_symmetric_(0),
upper_hermitian_(0),
lower_hermitian_(0),
general_(0),
one_base_(0),
Mb_(0),
Nb_(0),
k_(0),
l_(0),
rowmajor_(0),
colmajor_(0),
opt_regular_(0),
opt_irregular_(1),
opt_block_(0),
opt_unassembled_(0),
K_(),
L_()
{}
int& num_rows() { return num_rows_; }
int& num_cols() { return num_cols_; }
int& num_nonzeros() { return num_nonzeros_;}
int num_rows() const { return num_rows_; }
int num_cols() const { return num_cols_; }
int num_nonzeros() const { return num_nonzeros_;}
int is_one_base() const { return (one_base_ ? 1 : 0); }
int is_zero_base() const { return (one_base_ ? 0 : 1); }
int is_void() const { return void_; }
int is_new() const { return nnew_; }
int is_open() const { return open_; }
int is_valid() const { return valid_; }
int is_unit_diag() const { return unit_diag_; }
int is_complex() const { return complex_;}
int is_real() const { return real_;}
int is_single_precision() const { return single_precision_;}
int is_double_precision() const { return double_precision_;}
int is_upper_triangular() const { return upper_triangular_;}
int is_lower_triangular() const { return lower_triangular_;}
int is_triangular() const { return upper_triangular_ ||
lower_triangular_; }
int is_lower_symmetric() const { return lower_symmetric_; }
int is_upper_symmetric() const { return upper_symmetric_; }
int is_symmetric() const { return upper_symmetric_ ||
lower_symmetric_; }
int is_lower_hermitian() const { return lower_hermitian_; }
int is_upper_hermitian() const { return upper_hermitian_; }
int is_hermitian() const { return lower_hermitian_ ||
upper_hermitian_; }
int is_general() const { return !( is_hermitian() || is_symmetric()) ; }
int is_lower_storage() const { return is_lower_triangular() ||
is_lower_symmetric() ||
is_lower_hermitian() ; }
int is_upper_storage() const { return is_upper_triangular() ||
is_upper_symmetric() ||
is_upper_hermitian() ; }
int is_opt_regular() const { return opt_regular_; }
int is_opt_irregular() const { return opt_irregular_; }
int is_opt_block() const { return opt_block_;}
int is_opt_unassembled() const { return opt_unassembled_;}
int K(int i) const { return (k_ ? i*k_ : K_[i] ); }
int L(int i) const { return (l_ ? i*l_ : L_[i] ); }
int is_rowmajor() const { return rowmajor_; }
int is_colmajor() const { return colmajor_; }
void set_one_base() { one_base_ = 1; }
void set_zero_base() { one_base_ = 0; }
void set_void() { void_ = 1; nnew_ = open_ = valid_ = 0;}
void set_new() { nnew_ = 1; void_ = open_ = valid_ = 0;}
void set_open() { open_ = 1; void_ = nnew_ = valid_ = 0;}
void set_valid() { valid_ = 1; void_ = nnew_ = open_ = 0; }
void set_unit_diag() { unit_diag_ = 1;}
void set_complex() {complex_ = 1; }
void set_real() { real_ = 1; }
void set_single_precision() { single_precision_ = 1; }
void set_double_precision() { double_precision_ = 1; }
void set_upper_triangular() { upper_triangular_ = 1; }
void set_lower_triangular() { lower_triangular_ = 1; }
void set_upper_symmetric() { upper_symmetric_ = 1; }
void set_lower_symmetric() { lower_symmetric_ = 1; }
void set_upper_hermitian() { upper_hermitian_ = 1; }
void set_lower_hermitian() { lower_hermitian_ = 1; }
void set_const_block_parameters(int Mb, int Nb, int k, int l)
{
Mb_ = Mb;
Nb_ = Nb;
k_ = k;
l_ = l;
}
void set_var_block_parameters(int Mb, int Nb, const int *k, const int *l)
{
Mb_ = Mb;
Nb_ = Nb;
k_ = 0;
l_ = 0;
K_.resize(Mb+1);
K_[0] = 0;
for (int i=0; i<Mb; i++)
K_[i+1] = k[i] + K_[i];
L_.resize(Nb+1);
L_[0] = 0;
for (int j=0; j<Mb; j++)
K_[j+1] = k[j] + K_[j];
}
virtual int end_construction()
{
if (is_open() || is_new())
{
set_valid();
return 0;
}
else
ERROR_RETURN(1);
}
virtual void print() const;
virtual void destroy() {};
virtual ~Sp_mat() {};
};
template <class T>
class TSp_mat : public Sp_mat
{
private:
vector< vector< pair<T, int> > > S;
vector<T> diag; /* optional diag if matrix is
triangular. Created
at end_construction() phase */
private:
inline T sp_dot_product( const vector< pair<T, int> > &r,
const T* x, int incx ) const
{
T sum(0);
if (incx == 1)
{
for ( typename vector< pair<T,int> >::const_iterator p = r.begin();
p < r.end(); p++)
{
//sum = sum + p->first * x[p->second];
sum += p->first * x[p->second];
}
}
else /* incx != 1 */
{
for ( typename vector< pair<T,int> >::const_iterator p = r.begin();
p < r.end(); p++)
{
//sum = sum + p->first * x[p->second * incx];
sum += p->first * x[p->second * incx];
}
}
return sum;
}
inline T sp_conj_dot_product( const vector< pair<T, int> > &r,
const T* x, int incx ) const
{
T sum(0);
if (incx == 1)
{
for ( typename vector< pair<T,int> >::const_iterator p = r.begin();
p < r.end(); p++)
{
sum += conj(p->first) * x[p->second];
}
}
else /* incx != 1 */
{
for ( typename vector< pair<T,int> >::const_iterator p = r.begin();
p < r.end(); p++)
{
//sum = sum + p->first * x[p->second * incx];
sum += conj(p->first) * x[p->second * incx];
}
}
return sum;
}
inline void sp_axpy( const T& alpha, const vector< pair<T,int> > &r,
T* y, int incy) const
{
if (incy == 1)
{
for (typename vector< pair<T,int> >::const_iterator p = r.begin();
p < r.end(); p++)
y[p->second] += alpha * p->first;
}
else /* incy != 1 */
{
for (typename vector< pair<T,int> >::const_iterator p = r.begin();
p < r.end(); p++)
y[incy * p->second] += alpha * p->first;
}
}
inline void sp_conj_axpy( const T& alpha, const vector< pair<T,int> > &r,
T* y, int incy) const
{
if (incy == 1)
{
for (typename vector< pair<T,int> >::const_iterator p = r.begin();
p < r.end(); p++)
y[p->second] += alpha * conj(p->first);
}
else /* incy != 1 */
{
for (typename vector< pair<T,int> >::const_iterator p = r.begin();
p < r.end(); p++)
y[incy * p->second] += alpha * conj(p->first);
}
}
void mult_diag(const T& alpha, const T* x, int incx, T* y, int incy)
const
{
const T* X = x;
T* Y = y;
typename vector<T>::const_iterator d= diag.begin();
for ( ; d < diag.end(); X+=incx, d++, Y+=incy)
{
*Y += alpha * *d * *X;
}
}
void mult_conj_diag(const T& alpha, const T* x, int incx, T* y, int incy)
const
{
const T* X = x;
T* Y = y;
typename vector<T>::const_iterator d= diag.begin();
for ( ; d < diag.end(); X+=incx, d++, Y+=incy)
{
*Y += alpha * conj(*d) * *X;
}
}
void nondiag_mult_vec(const T& alpha, const T* x, int incx,
T* y, int incy) const
{
int M = num_rows();
if (incy == 1)
{
for (int i=0; i<M; i++)
y[i] += alpha * sp_dot_product(S[i], x, incx);
}
else
{
for (int i=0; i<M; i++)
y[i * incy] += alpha * sp_dot_product(S[i], x, incx);
}
}
void nondiag_mult_vec_conj(const T& alpha, const T* x, int incx,
T* y, int incy) const
{
int M = num_rows();
if (incy == 1)
{
for (int i=0; i<M; i++)
y[i] += alpha * sp_conj_dot_product(S[i], x, incx);
}
else
{
for (int i=0; i<M; i++)
y[i * incy] += alpha * sp_conj_dot_product(S[i], x, incx);
}
}
void nondiag_mult_vec_transpose(const T& alpha, const T* x, int incx,
T* y, int incy) const
{
/* saxpy: y += (alpha * x[i]) row[i] */
int M = num_rows();
const T* X = x;
for (int i=0; i<M; i++, X += incx)
sp_axpy( alpha * *X, S[i], y, incy);
}
void nondiag_mult_vec_conj_transpose(const T& alpha, const T* x, int incx,
T* y, int incy) const
{
/* saxpy: y += (alpha * x[i]) row[i] */
int M = num_rows();
const T* X = x;
for (int i=0; i<M; i++, X += incx)
sp_conj_axpy( alpha * *X, S[i], y, incy);
}
void mult_vec(const T& alpha, const T* x, int incx, T* y, int incy)
const
{
nondiag_mult_vec(alpha, x, incx, y, incy);
if (is_triangular() || is_symmetric())
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -