Files
secondo/Tools/Generators/MultivarDist/GSL_LinearAlgebra.h

235 lines
4.2 KiB
C
Raw Normal View History

2026-01-23 17:03:45 +08:00
/*
Nov. 2008 M. Spiekermann
The classes GMatrix and GVector were introduced in order to
provide a more readable programming interface for GSL types and
operations. In its initial version the supported features are
very limited since I only need a cholesky decomposition in order
to provide the generation of random sequences for
multivariate normal distribution
*/
#ifndef SEC_GSL_LINALG_H
#define SEC_GSL_LINALG_H
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_linalg.h>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <assert.h>
class GMatrix;
class GVector {
public:
GVector(size_t size, double val = 0.0 )
{
v = gsl_vector_alloc(size);
gsl_vector_set_all(v, val);
refs = 1;
}
inline GVector(const GVector& rhs) : v(rhs.v) { refs++; }
inline GVector& operator=(const GVector& rhs)
{
v = rhs.v;
refs++;
return *this;
}
~GVector()
{
refs--;
if (refs == 0) {
gsl_vector_free(v);
}
}
inline GVector operator*(const GMatrix& m) const;
inline const double& operator[] (size_t i) const
{
return v->data[i * v->stride];
}
inline double& operator[] (size_t i)
{
return v->data[i * v->stride];
}
inline size_t getDim() const { return v->size; }
inline void put(ostream& os, const string& sep) const
{
ios_base::fmtflags oldflags = os.flags();
os << setprecision(2) << fixed;
size_t i = 0;
for ( ;i < getDim()-1; i++) {
os << (*this)[i] << sep;
}
os << (*this)[i];
os.flags(oldflags);
}
private:
gsl_vector* v;
size_t refs;
};
class GMatrix {
public:
GMatrix(size_t rows, size_t cols, double val = 0.0)
{
m = gsl_matrix_alloc(rows, cols);
gsl_matrix_set_all(m, val);
}
~GMatrix()
{
gsl_matrix_free(m);
}
inline const double* operator[] (size_t i) const
{
return &(m->data[i * m->tda]);
}
inline double* operator[] (size_t i)
{
return &(m->data[i * m->tda]);
}
inline GVector operator*(const GVector& v) const
{
assert( v.getDim() == getCols() );
GVector r( v.getDim() );
for(int i = 0; i < getRows(); i++) {
for(int j = 0; j < getCols(); j++) {
r[i] += (*this)[i][j] * v[j];
}
}
return r;
}
inline size_t getRows() const { return m->size1; }
inline size_t getCols() const { return m->size2; }
void setDiag(double val)
{
for(int i = 0; i < min(getRows(), getCols()); i++) {
(*this)[i][i] = val;
}
}
void topRight_to_lowerLeft()
{
size_t k = min( getRows(), getCols() );
for(int i = 0; i < k; i++) {
for(int j = i+1; j < k; j++) {
(*this)[j][i] = (*this)[i][j];
}
}
}
void set_topRight(double val = 0.0, const bool topRight = true)
{
size_t k = min( getRows(), getCols() );
for(int i = 0; i < k; i++) {
for(int j = i+1; j < k; j++) {
if (topRight) {
(*this)[i][j] = val;
} else {
(*this)[j][i] = val;
}
}
}
}
void set_lowerLeft(double val = 0.0)
{
set_topRight(val, false);
}
void doCholeskyDecomposition() {
// to do error handling !!!
gsl_linalg_cholesky_decomp(m);
}
private:
gsl_matrix* m;
};
inline GVector GVector::operator*(const GMatrix& m) const
{
assert( getDim() == m.getRows() );
GVector r( m.getRows() );
for(int i = 0; i < getDim(); i++) {
for(int j = 0; j < m.getRows(); j++) {
//cout << (*this)[j] << " * " << m[j][i]
//<< " = " << (*this)[j] * m[j][i] << endl;
r[i] += (*this)[j] * m[j][i];
}
}
return r;
}
ostream& operator<<(ostream& os, const GMatrix& m)
{
ios_base::fmtflags oldflags = os.flags();
os << setprecision(2) << fixed;
for (size_t i = 0; i < m.getRows(); i++) {
for (size_t j = 0; j < m.getCols(); j++) {
os << m[i][j] << " ";
}
os << endl;
}
os.flags(oldflags);
return os;
}
ostream& operator<<(ostream& os, const GVector& v)
{
os << "( ";
v.put(os, ", ");
os << " )" << endl;
return os;
}
#endif