34 namespace xerus {
namespace internal {
42 CholmodCommon::RestrictedAccess::operator cholmod_common*()
const {
50 static void error_handler(
int status,
const char *file,
int line,
const char *message) {
52 LOG(fatal,
"CHOLMOD had a fatal error in " << file <<
":" << line <<
" (status: " << status <<
") msg: " << message);
54 LOG(cholmod_warning,
"CHOLMOD warns in " << file <<
":" << line <<
" (status: " << status <<
") msg: " << message);
59 cholmod_l_start(
c.get());
60 REQUIRE(
c->itype == CHOLMOD_LONG,
"atm only cholmod compiled with itype = long is supported...");
61 REQUIRE(
c->dtype == CHOLMOD_DOUBLE,
"atm only cholmod compiled with dtype = double is supported...");
64 REQUIRE(
c->status == 0,
"unable to initialize CHOLMOD");
68 cholmod_l_finish(
c.get());
76 return [&](cholmod_sparse* _toDelete) {
77 cholmod_l_free_sparse(&_toDelete, this->
get());
89 :
matrix(cholmod_l_allocate_sparse(_m, _n, _N, 1, 1, 0, CHOLMOD_REAL, cholmodObject.get()), cholmodObject.get_deleter())
91 REQUIRE(
matrix && cholmodObject.c->status == 0,
"cholmod_allocate_sparse did not allocate anything... status: " << cholmodObject.c->status <<
" call: " << _m <<
" " << _n <<
" " << _N <<
" alloc: " << cholmodObject.c->malloc_count);
98 long* i =
static_cast<long*
>(
matrix->i);
99 long* p =
static_cast<long*
>(
matrix->p);
100 double* x =
static_cast<double*
>(
matrix->x);
107 for(
const auto& entry : _input) {
108 x[entryPos] = entry.second;
109 i[entryPos] =
static_cast<long>(entry.first%_n);
110 while(currRow < static_cast<long>(entry.first/_n)) {
111 p[++currRow] = long(entryPos);
116 REQUIRE(currRow <
long(_m) && entryPos == _input.size(),
"cholmod error - invalid input? " << currRow <<
", " << _m <<
" | " << entryPos <<
", " << _input.size());
118 while(currRow < static_cast<long>(_m)) {
119 p[++currRow] = long(entryPos);
129 std::map<size_t, double> result;
130 long* mi =
reinterpret_cast<long*
>(
matrix->i);
131 long* p =
reinterpret_cast<long*
>(
matrix->p);
132 double* x =
reinterpret_cast<double*
>(
matrix->x);
134 for(
size_t i = 0; i <
matrix->ncol; ++i) {
135 for(
long j = p[i]; j < p[i+1]; ++j) {
136 IF_CHECK(
auto ret = ) result.emplace(
size_t(mi[
size_t(j)])*
matrix->ncol+i, _alpha*x[j]);
148 ptr_type newM(cholmod_l_allocate_sparse(
matrix->ncol,
matrix->nrow,
matrix->nzmax, 1, 1, 0, CHOLMOD_REAL, cholmodObject.get()), cholmodObject.get_deleter());
149 cholmod_l_transpose_unsym(
matrix.get(), 1,
nullptr,
nullptr, 0, newM.get(), cholmodObject.get());
155 const size_t _leftDim,
156 const size_t _rightDim,
158 const std::map<size_t, double>& _A,
159 const bool _transposeA,
160 const size_t _midDim,
161 const std::map<size_t, double>& _B,
162 const bool _transposeB )
165 const CholmodSparse lhsCs(_A, _transposeA?_midDim:_leftDim, _transposeA?_leftDim:_midDim, _transposeA);
166 const CholmodSparse rhsCs(_B, _transposeB?_rightDim:_midDim, _transposeB?_midDim:_rightDim, _transposeB);
168 _C = resultCs.
to_map(_alpha);
173 const std::map<size_t, double>& _A,
174 const bool _transposeA,
175 const std::map<size_t, double>&
_b,
178 const CholmodSparse A(_A, _transposeA?_xDim:_bDim, _transposeA?_bDim:_xDim, _transposeA);
187 const std::map<size_t, double>& _A,
188 const bool _transposeA,
192 REQUIRE(_xDim < std::numeric_limits<long>::max() && _bDim < std::numeric_limits<long>::max() && _A.size() < std::numeric_limits<long>::max(),
193 "sparse matrix given to qc decomposition too large for suitesparse" 195 const CholmodSparse A(_A, _transposeA?_xDim:_bDim, _transposeA?_bDim:_xDim, _transposeA);
197 _bDim, 1, _bDim, _bDim,
198 static_cast<void*
>(
const_cast<double*
>(
_b)),
nullptr,
199 CHOLMOD_REAL, CHOLMOD_DOUBLE
201 std::unique_ptr<cholmod_dense, std::function<void(cholmod_dense*)>> x(
202 SuiteSparseQR<double>(A.matrix.get(), &b, cholmodObject.get()),
203 [](cholmod_dense* _toDelete) {
204 cholmod_l_free_dense(&_toDelete, cholmodObject.get());
209 misc::copy(_x, static_cast<double*>(x->x), _xDim);
214 const std::map<size_t, double> &_A,
215 const bool _transposeA,
220 REQUIRE(_m < std::numeric_limits<long>::max() && _n < std::numeric_limits<long>::max() && _A.size() < std::numeric_limits<long>::max(),
221 "sparse matrix given to qc decomposition too large for suitesparse" 223 REQUIRE(_m>0 && _n>0,
"invalid matrix of dimensions " << _m <<
'x' << _n);
225 cholmod_sparse *Q, *R;
227 long rank = SuiteSparseQR<double>(0,
xerus::EPSILON, _fullrank?long(std::min(_m,_n)):1, A.
matrix.get(), &Q, &R, &E, cholmodObject.get());
228 rank = std::max(rank, 1l);
231 INTERNAL_CHECK(E ==
nullptr,
"IE: sparse QR returned a permutation despite fixed ordering?!");
232 INTERNAL_CHECK(rank>=0,
"SuiteSparseQR returned negative value " << rank);
233 INTERNAL_CHECK((_fullrank?std::min(_m,_n):
size_t(rank)) == Qs.
matrix->ncol,
"IE: strange rank deficiency after sparse qr " << (_fullrank?
long(std::min(_m,_n)):rank) <<
" vs " << Qs.
matrix->ncol);
234 return std::make_tuple(Qs.
to_map(), Rs.
to_map(), _fullrank?std::min(_m,_n):size_t(rank));
238 const std::map<size_t, double> &_A,
239 const bool _transposeA,
244 REQUIRE(_m < std::numeric_limits<long>::max() && _n < std::numeric_limits<long>::max() && _A.size() < std::numeric_limits<long>::max(),
245 "sparse matrix given to qc decomposition too large for suitesparse" 248 cholmod_sparse *Q, *R;
251 long rank = SuiteSparseQR<double>(0,
xerus::EPSILON, _fullrank?long(std::min(_m,_n)):1, A.matrix.get(), &Q, &R, &E, cholmodObject.get());
252 rank = std::max(rank, 1l);
255 INTERNAL_CHECK(E ==
nullptr,
"IE: sparse QR returned a permutation despite fixed ordering?!");
256 INTERNAL_CHECK(rank>=0,
"SuiteSparseQR returned negative value " << rank);
257 INTERNAL_CHECK((_fullrank?std::min(_m,_n):
size_t(rank)) == Qs.
matrix->ncol,
"IE: strange rank deficiency after sparse qr " << (_fullrank?
long(std::min(_m,_n)):rank) <<
" vs " << Qs.
matrix->ncol);
261 return std::make_tuple(Rs.
to_map(), Qs.
to_map(), _fullrank?std::min(_m,_n):size_t(rank));
Header file for CHECK and REQUIRE macros.
thread_local CholmodCommon cholmodObject
std::function< void(cholmod_sparse *)> get_deleter()
std::map< size_t, double > to_map(double _alpha=1.0) const
Transforms a cholmod sparse matrix to sparse Tensor format.
Header file for the Index class.
RestrictedAccess(cholmod_common *const _c, std::mutex &_lock)
The main namespace of xerus.
CholmodSparse operator*(const CholmodSparse &_rhs) const
Calculates the Matrix Matrix product with another sparse matrix.
Header file for the Tensor class.
wrapper class for the cholmod sparse matrix objects
void transpose()
transposes the represented sparse matrix.
static std::tuple< std::map< size_t, double >, std::map< size_t, double >, size_t > cq(const std::map< size_t, double > &_A, const bool _transposeA, size_t _m, size_t _n, bool _fullrank)
calculates the sparse CQ decomposition
wrapper object for the cholmod_common struct to automatically call the constructor and destructor ...
std::unique_ptr< cholmod_common > c
Header file for the low level array support function.
Header file for comfort functions and macros that should not be exported in the library.
constexpr const value_t EPSILON
The default epsilon value in xerus.
static void solve_dense_rhs(double *_x, size_t _xDim, const std::map< size_t, double > &_A, const bool _transposeA, const double *_b, size_t _bDim)
solve operator / for dense right hand sites
CholmodSparse(cholmod_sparse *_matrix)
stores the given cholmod_sparse object in this wrapper. NOTE: the object must have been created by th...
Header file for suitesparse wrapper functions.
static void matrix_matrix_product(std::map< size_t, double > &_C, const size_t _leftDim, const size_t _rightDim, const double _alpha, const std::map< size_t, double > &_A, const bool _transposeA, const size_t _midDim, const std::map< size_t, double > &_B, const bool _transposeB)
Calculates the Matrix Matrix product between two sparse matrices.
std::unique_ptr< cholmod_sparse, std::function< void(cholmod_sparse *)> > ptr_type
void copy(T *const __restrict _dest, const T *const __restrict _src, const size_t _n) noexcept
Copys _n entries from _y to _x, where _y and _x must be disjunkt memory regions.
static std::tuple< std::map< size_t, double >, std::map< size_t, double >, size_t > qc(const std::map< size_t, double > &_A, const bool _transposeA, size_t _m, size_t _n, bool _fullrank)
calculates the sparse QR decomposition (or qc if fullrank = false)
static void error_handler(int status, const char *file, int line, const char *message)
static void solve_sparse_rhs(std::map< size_t, double > &_x, size_t _xDim, const std::map< size_t, double > &_A, const bool _transposeA, const std::map< size_t, double > &_b, size_t _bDim)
solve operator / for sparse right hand sites