3 #ifndef COMMON_TENSOR_HPP_ 4 #define COMMON_TENSOR_HPP_ 12 #include <type_traits> 38 unsigned int rand_seed;
44 UVEC cumprod_dims_shifted = arma::shift(cumprod_dims, 1);
45 cumprod_dims_shifted(0) = 1;
46 size_t idx = arma::dot(cumprod_dims_shifted, sub);
59 UVEC cumprod_dims_shifted = arma::shift(cumprod_dims, 1);
60 cumprod_dims_shifted(0) = 1;
64 for (
int i =
modes - 1; i >= 0; i--) {
65 temp = std::floor((idx * 1.0) / (cumprod_dims_shifted(i) * 1.0));
67 idx = idx - cumprod_dims_shifted(i) * temp;
83 : m_modes(i_dimensions.n_rows),
84 m_dimensions(i_dimensions),
85 m_numel(arma::prod(i_dimensions)),
91 : m_modes(i_dimensions.n_rows),
92 m_dimensions(i_dimensions),
93 m_numel(arma::prod(i_dimensions)),
94 m_global_idx(i_start_idx),
105 : m_modes(i_dimensions.n_rows),
106 m_dimensions(i_dimensions),
107 m_numel(arma::prod(i_dimensions)),
110 memcpy(&this->m_data[0], i_data,
sizeof(
double) * this->m_numel);
119 this->m_numel = src.
numel();
120 this->m_modes = src.
modes();
123 this->rand_seed = 103;
124 this->m_data = src.
m_data;
128 if (
this != &other) {
131 this->m_numel = other.
numel();
132 this->m_modes = other.
modes();
135 this->m_data = other.
m_data;
142 swap(m_numel, in.m_numel);
143 swap(m_modes, in.m_modes);
144 swap(m_dimensions, in.m_dimensions);
145 swap(m_global_idx, in.m_global_idx);
146 swap(rand_seed, in.rand_seed);
155 this->m_data.clear();
159 int modes()
const {
return m_modes; }
174 void set_idx(
const UVEC &i_start_idx) { m_global_idx = i_start_idx; }
181 UWORD rc = arma::prod(this->m_dimensions);
182 return rc - this->m_dimensions(i);
186 for (
UWORD i = 0; i < this->m_numel; i++) {
192 #pragma omp parallel for 193 for (
UWORD i = 0; i < this->m_numel; i++) {
194 unsigned int *temp =
const_cast<unsigned int *
>(&rand_seed);
196 static_cast<double>(rand_r(temp)) / static_cast<double>(RAND_MAX);
201 std::random_device rd;
202 std::mt19937 gen(rd());
203 int max_randi = this->m_numel;
204 std::uniform_int_distribution<> dis(0, max_randi);
205 #pragma omp parallel for 206 for (
UWORD i = 0; i < this->m_numel; i++) {
207 this->m_data[i] = dis(gen);
216 std::random_device rd;
217 std::uniform_real_distribution<> dis(0, 1);
219 std::mt19937 gen(rand_seed);
220 #pragma omp parallel for 221 for (
unsigned int i = 0; i < this->m_numel; i++) {
225 std::mt19937 gen(i_seed);
226 #pragma omp parallel for 227 for (
unsigned int i = 0; i < this->m_numel; i++) {
262 int m = this->m_dimensions[0];
263 int n = i_krp.n_cols;
264 int k = i_krp.n_rows;
275 cblas_dgemm(CblasRowMajor, CblasTrans, CblasTrans, m, n, k, alpha,
276 &this->m_data[0], m, i_krp.memptr(), k, beta,
277 o_mttkrp->memptr(), n);
282 int lowrankk = i_krp.n_cols;
285 for (
int i = 0; i < i_n; i++) {
286 ncols *= this->m_dimensions[i];
290 for (
int i = i_n + 1; i < this->m_modes; i++) {
291 nmats *= this->m_dimensions[i];
294 for (
int i = 0; i < nmats; i++) {
297 int m = this->m_dimensions[i_n];
304 double beta = (i == 0) ? 0 : 1;
318 cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasTrans, m, n, k, alpha,
319 &this->m_data[0] + i * k * m, ncols, i_krp.memptr() + i * k,
320 ncols * nmats, beta, o_mttkrp->memptr(), n);
326 INFO <<
"Dimensions: " << this->m_dimensions;
327 for (
unsigned int i = 0; i < this->m_numel; i++) {
328 std::cout << i <<
" : " << this->m_data[i] << std::endl;
333 UVEC local_sub = arma::zeros<UVEC>(global_dims.n_elem);
335 UVEC global_sub = arma::zeros<UVEC>(global_dims.n_elem);
337 for (
unsigned int i = 0; i < this->m_numel; i++) {
338 local_sub = ind2sub(this->m_dimensions, i);
339 global_sub = global_start_sub + local_sub;
340 global_idx = sub2ind(global_sub, global_dims);
341 std::cout << i <<
" : " <<
global_idx <<
" : " << this->m_data[i]
348 for (
unsigned int i = 0; i < this->m_numel; i++) {
349 norm_fro += (this->m_data[i] * this->m_data[i]);
360 for (
unsigned int i = 0; i < this->m_numel; i++) {
361 err_diff = this->m_data[i] - b.
m_data[i];
362 norm_fro += err_diff * err_diff;
371 template <
typename NumericType>
375 for (
unsigned int i = 0; i < this->m_numel; i++) {
376 this->m_data[i] = this->m_data[i] *
scale;
384 template <
typename NumericType>
388 for (
unsigned int i = 0; i < this->m_numel; i++) {
389 this->m_data[i] = this->m_data[i] + i_shift;
398 template <
typename NumericType>
399 void bound(NumericType min, NumericType max) {
402 for (
unsigned int i = 0; i < this->m_numel; i++) {
403 if (this->m_data[i] < min) this->m_data[i] = min;
404 if (this->m_data[i] > max) this->m_data[i] = max;
412 template <
typename NumericType>
416 for (
unsigned int i = 0; i < this->m_numel; i++) {
417 if (this->m_data[i] < min) this->m_data[i] = min;
427 std::ios_base::openmode mode = std::ios_base::out) {
428 std::string filename_no_extension =
429 filename.substr(0, filename.find_last_of(
"."));
431 filename_no_extension.append(
".info");
433 ofs.open(filename_no_extension, std::ios_base::out);
435 ofs << this->m_modes << std::endl;
437 for (
int i = 0; i < this->m_modes; i++) {
438 ofs << this->m_dimensions[i] << std::endl;
442 FILE *fp = fopen(filename.c_str(),
"wb");
443 INFO <<
"size of the outputfile in GB " 444 << (this->m_numel * 8.0) / (1024 * 1024 * 1024) << std::endl;
446 fwrite(&this->m_data[0],
sizeof(std::vector<double>::value_type),
448 if (nwrite != this->
numel()) {
449 WARN <<
"something wrong ::write::" << nwrite
450 <<
"::numel::" << this->
numel() << std::endl;
460 void read(std::string filename,
461 std::ios_base::openmode mode = std::ios_base::in) {
463 if (this->m_numel > 0) {
464 this->m_data.clear();
467 std::string filename_no_extension =
468 filename.substr(0, filename.find_last_of(
"."));
469 filename_no_extension.append(
".info");
473 ifs.open(filename_no_extension, std::ios_base::in);
475 ifs >> this->m_modes;
477 this->m_dimensions = arma::zeros<UVEC>(this->m_modes);
478 for (
int i = 0; i < this->m_modes; i++) {
479 ifs >> this->m_dimensions[i];
483 FILE *fp = fopen(filename.c_str(),
"rb");
484 this->m_numel = arma::prod(this->m_dimensions);
485 this->m_data.resize(this->m_numel);
491 fread(&this->m_data[0],
sizeof(std::vector<double>::value_type),
493 if (nread != this->
numel()) {
494 WARN <<
"something wrong ::write::" << nread
495 <<
"::numel::" << this->
numel() << std::endl;
509 assert(sub.n_cols == this->m_dimensions.n_cols);
510 UVEC cumprod_dims = arma::cumprod(this->m_dimensions);
511 UVEC cumprod_dims_shifted = arma::shift(cumprod_dims, 1);
512 cumprod_dims_shifted(0) = 1;
513 size_t idx = arma::dot(cumprod_dims_shifted, sub);
522 #endif // COMMON_TENSOR_HPP_ Tensor(const UVEC &i_dimensions)
Constructor that takes only dimensions of every mode as a vector.
Tensor(const UVEC &i_dimensions, double *i_data)
Need when copying from matrix to Tensor.
Data is stored such that the unfolding is column major.
Tensor(const Tensor &src)
copy constructor
void print(const UVEC &global_dims, const UVEC &global_start_sub)
void zeros()
Zeros out the entire tensor.
double err(const Tensor &b) const
Computes the squared error with the input tensor.
std::vector< double > m_data
void mttkrp(const int i_n, const MAT &i_krp, MAT *o_mttkrp) const
size of krp must be product of all dimensions leaving out nxk.
void lower_bound(NumericType min)
Sets only the lower bound.
void print() const
prints the value of the tensor.
void shift(NumericType i_shift)
Shifts (add or subtract) the tensor with the constant value.
void read(std::string filename, std::ios_base::openmode mode=std::ios_base::in)
Reads a tensor from the file.
void swap(planc::Tensor &x, planc::Tensor &y)
void randu(const int i_seed=-1)
set the tensor with uniform random values starting with a seed.
Tensor(const UVEC &i_dimensions, const UVEC &i_start_idx)
UWORD sub2ind(UVEC sub)
Given a vector of subscripts, it return the linear index in the tensor.
void randi()
set the tensor with uniform int values
void rand()
set the tensor with uniform random.
int modes() const
Return the number of modes. It is a scalar value.
void bound(NumericType min, NumericType max)
Truncate all the value between min and max.
void set_idx(const UVEC &i_start_idx)
void write(std::string filename, std::ios_base::openmode mode=std::ios_base::out)
Write the tensor to the given filename.
UVEC dimensions() const
Returns a vector of dimensions on every mode.
void scale(NumericType scale)
Scales the tensor with the constant value.
UWORD numel() const
Returns total number of elements.
int dimension(int i) const
Returns the dimension of the input mode.
double norm() const
returns the frobenius norm of the tensor
Tensor & operator=(const Tensor &other)
ncp_factors contains the factors of the ncp every ith factor is of size n_i * k number of factors is ...
void clear()
Clears the data and also destroys the storage.
UWORD dimensions_leave_out_one(int i) const
Return the product of dimensions except mode i.