#include <algorithm>
#include <eigen3/Eigen/SparseCore>
#include <fstream>
#include <iostream>
#include <utility>
#include <vector>
template <typename ValueType>
ValueType naive_atot(const char *p) {
ValueType r = 0.0;
bool neg = false;
while (*p == ' ') ++p;
if (*p == '-') {
neg = true;
++p;
} else if (*p == '+') {
++p;
}
while (*p >= '0' && *p <= '9') {
r = (r * 10.0) + (*p - '0');
++p;
}
if (*p == '.') {
ValueType f = 0.0;
int n = 0;
++p;
while (*p >= '0' && *p <= '9') {
f = (f * 10.0) + (*p - '0');
++p;
++n;
}
r += f / std::pow(10.0, n);
}
if (neg) {
r = -r;
}
return r;
}
// for readline (used in load libsvm)
static char *my_line = nullptr;
static int max_line_len;
static inline char *readline(FILE *input) {
if (fgets(my_line, max_line_len, input) == nullptr) return nullptr;
while (strrchr(my_line, '\n') == nullptr) {
max_line_len *= 2;
my_line = (char *)realloc(my_line, max_line_len);
int len = (int)strlen(my_line);
if (fgets(my_line + len, max_line_len - len, input) == nullptr) break;
}
return my_line;
}
template <typename Scalar, int Major, typename Index>
bool load_libsvm(Eigen::SparseMatrix<Scalar, Major, Index> &spa_x,
Eigen::Array<Scalar, Eigen::Dynamic, 1> &y,
const std::string &file_name,
const bool &flag_remove_zero = true) {
FILE *fp = fopen(file_name.c_str(), "r");
if (fp == nullptr) return false;
using Tri = Eigen::Triplet<Scalar>;
std::vector<Tri> tripletList;
tripletList.reserve(1024);
y.resize(1024);
max_line_len = 1024;
my_line = (char *)malloc(max_line_len * sizeof(char));
unsigned int n = 0, d = 0, k = 0, num_ele = 0;
while (readline(fp) != nullptr) {
char *p = strtok(my_line, " \t\n");
if (p == nullptr) return false;
y[n] = naive_atot<Scalar>(p);
num_ele = 0;
while (1) {
char *idx = strtok(nullptr, ":");
char *val = strtok(nullptr, " \t");
if (val == nullptr) break;
++num_ele;
k = strtol(idx, nullptr, 10) - 1;
if (d < k) d = k;
tripletList.emplace_back(Tri(n, k, naive_atot<Scalar>(val)));
}
if (!flag_remove_zero || (flag_remove_zero && num_ele > 0)) ++n;
if (static_cast<unsigned int>(y.size()) <= n) {
y.conservativeResize(y.size() * 2);
tripletList.reserve(y.size() * 2);
}
}
fclose(fp);
free(my_line);
++d;
y.conservativeResize(n);
spa_x.resize(n, d);
spa_x.setFromTriplets(tripletList.begin(), tripletList.end());
spa_x.makeCompressed();
return true;
}
int main(int argc, char *argv[]) {
using namespace std;
Eigen::SparseMatrix<float, 1, std::ptrdiff_t> sx;
Eigen::Array<float, Eigen::Dynamic, 1> y;
const std::string fn = argv[1];
load_libsvm(sx, y, fn, false);
std::cout << sx.rows() << ", " << sx.nonZeros() << std::endl;
return 0;
}