Количество элементов в матрице всегда n × m
, независимо от стратегии хранения (разреженной или плотной).
Поэтому вы не должны удивляться, что сможете прочитать ячейки «0» - они не могут быть сохранены, но очевидно, что они важны для вычислений, поэтому вы должны иметь возможность получить их значение.
В свете этого, ваш эскиз (с memptr()
, который я предполагаю, был Копирование / вставка из некоторого кода, указанного c в не разреженные матрицы) всегда будет хранить не разреженные данные (вы повторяете все n_elems
). Но data
не может указывать на какое-то смежное хранилище, потому что как матрица узнает, какие ячейки существуют, если только разметка памяти не совпадает с размерами матрицы напрямую (плотное хранилище, основной ряд или основной столбец).
На основе на информацию из Возвращение местоположений и значений разреженной матрицы в Armadillo C ++ вот фиксированная реализация:
- НЕ пытается использовать недокументированные детали реализации
- использует документированный интерфейс (it.col (), it.row ()) для редкой сериализации
- работает
Полный код (проверено на моей машине):
#include <iostream>
#include <fstream>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <armadillo>
#include <boost/serialization/split_member.hpp>
BOOST_SERIALIZATION_SPLIT_FREE(arma::sp_mat)
namespace boost {
namespace serialization {
template<class Archive>
void save(Archive & ar, const arma::sp_mat &t, unsigned) {
ar & t.n_rows;
ar & t.n_cols;
for (auto it = t.begin(); it != t.end(); ++it) {
ar & it.row() & it.col() & *it;
}
}
template<class Archive>
void load(Archive & ar, arma::sp_mat &t, unsigned) {
uint64_t r, c;
ar & r;
ar & c;
t.set_size(r, c);
for (auto it = t.begin(); it != t.end(); ++it) {
double v;
ar & r & c & v;
t(r, c) = v;
}
}
}}
int main() {
arma::mat C(3,3, arma::fill::randu);
C(1,1) = 0; //example so that a few of the components are u
C(1,2) = 0;
C(0,0) = 0;
C(2,1) = 0;
C(2,0) = 0;
{
arma::sp_mat const A = arma::sp_mat(C);
A.print("A: ");
std::ofstream outputStream("bin.dat", std::ios::binary);
boost::archive::binary_oarchive oa(outputStream);
oa & A;
}
{
std::ifstream inputStream("bin.dat", std::ios::binary);
boost::archive::binary_iarchive ia(inputStream);
arma::sp_mat B;
ia & B;
B.print("B: ");
}
}
Отпечатки
A:
[matrix size: 3x3; n_nonzero: 4; density: 44.44%]
(1, 0) 0.2505
(0, 1) 0.9467
(0, 2) 0.2513
(2, 2) 0.5206
B:
[matrix size: 3x3; n_nonzero: 4; density: 44.44%]
(1, 0) 0.2505
(0, 1) 0.9467
(0, 2) 0.2513
(2, 2) 0.5206